Browse code

Reduce memory allocation and remove channels

Signed-off-by: Sachin Joshi <sachin_jayant_joshi@hotmail.com>

Sachin Joshi authored on 2015/03/20 10:07:56
Showing 2 changed files
... ...
@@ -26,15 +26,15 @@ const (
26 26
 )
27 27
 
28 28
 func main() {
29
+	if reexec.Init() {
30
+		return
31
+	}
32
+
29 33
 	// Set terminal emulation based on platform as required.
30 34
 	stdout, stderr, stdin := term.StdStreams()
31 35
 
32 36
 	initLogging(stderr)
33 37
 
34
-	if reexec.Init() {
35
-		return
36
-	}
37
-
38 38
 	flag.Parse()
39 39
 	// FIXME: validate daemon flags here
40 40
 
... ...
@@ -83,6 +83,7 @@ const (
83 83
 
84 84
 	ANSI_MAX_CMD_LENGTH = 256
85 85
 
86
+	MAX_INPUT_EVENTS = 128
86 87
 	MAX_INPUT_BUFFER = 1024
87 88
 	DEFAULT_WIDTH    = 80
88 89
 	DEFAULT_HEIGHT   = 24
... ...
@@ -195,15 +196,18 @@ type (
195 195
 type WindowsTerminal struct {
196 196
 	outMutex            sync.Mutex
197 197
 	inMutex             sync.Mutex
198
-	inputBuffer         chan byte
198
+	inputBuffer         []byte
199
+	inputSize           int
200
+	inputEvents         []INPUT_RECORD
199 201
 	screenBufferInfo    *CONSOLE_SCREEN_BUFFER_INFO
200 202
 	inputEscapeSequence []byte
201 203
 }
202 204
 
203 205
 func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
204 206
 	handler := &WindowsTerminal{
205
-		inputBuffer:         make(chan byte, MAX_INPUT_BUFFER),
207
+		inputBuffer:         make([]byte, MAX_INPUT_BUFFER),
206 208
 		inputEscapeSequence: []byte(KEY_ESC_CSI),
209
+		inputEvents:         make([]INPUT_RECORD, MAX_INPUT_EVENTS),
207 210
 	}
208 211
 
209 212
 	// Save current screen buffer info
... ...
@@ -218,6 +222,8 @@ func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
218 218
 
219 219
 	// Set the window size
220 220
 	SetWindowSize(uintptr(handle), DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_HEIGHT)
221
+	buffer = make([]CHAR_INFO, screenBufferInfo.MaximumWindowSize.X*screenBufferInfo.MaximumWindowSize.Y)
222
+
221 223
 	if IsTerminal(os.Stdout.Fd()) {
222 224
 		stdOut = &terminalWriter{
223 225
 			wrappedWriter: os.Stdout,
... ...
@@ -427,6 +433,8 @@ func getNumberOfChars(fromCoord COORD, toCoord COORD, screenSize COORD) uint32 {
427 427
 	return 0
428 428
 }
429 429
 
430
+var buffer []CHAR_INFO
431
+
430 432
 func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (bool, uint32, error) {
431 433
 	var writeRegion SMALL_RECT
432 434
 	writeRegion.Top = fromCoord.Y
... ...
@@ -439,14 +447,13 @@ func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoor
439 439
 	height := toCoord.Y - fromCoord.Y + 1
440 440
 	size := width * height
441 441
 	if size > 0 {
442
-		buffer := make([]CHAR_INFO, size)
443
-		for i := 0; i < len(buffer); i++ {
442
+		for i := 0; i < int(size); i++ {
444 443
 			buffer[i].UnicodeChar = WCHAR(fillChar)
445 444
 			buffer[i].Attributes = attributes
446 445
 		}
447 446
 
448 447
 		// Write to buffer
449
-		r, err := writeConsoleOutput(fileDesc, buffer, windowSize, COORD{X: 0, Y: 0}, &writeRegion)
448
+		r, err := writeConsoleOutput(fileDesc, buffer[:size], windowSize, COORD{X: 0, Y: 0}, &writeRegion)
450 449
 		if !r {
451 450
 			if err != nil {
452 451
 				return false, 0, err
... ...
@@ -914,6 +921,9 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
914 914
 
915 915
 // WriteChars writes the bytes to given writer.
916 916
 func (term *WindowsTerminal) WriteChars(fd uintptr, w io.Writer, p []byte) (n int, err error) {
917
+	if len(p) == 0 {
918
+		return 0, nil
919
+	}
917 920
 	return w.Write(p)
918 921
 }
919 922
 
... ...
@@ -1049,24 +1059,19 @@ func mapKeystokeToTerminalString(keyEvent *KEY_EVENT_RECORD, escapeSequence []by
1049 1049
 
1050 1050
 // getAvailableInputEvents polls the console for availble events
1051 1051
 // The function does not return until at least one input record has been read.
1052
-func getAvailableInputEvents(fd uintptr) (inputEvents []INPUT_RECORD, err error) {
1052
+func getAvailableInputEvents(fd uintptr, inputEvents []INPUT_RECORD) (n int, err error) {
1053 1053
 	handle := syscall.Handle(fd)
1054 1054
 	if nil != err {
1055
-		return nil, err
1055
+		return 0, err
1056 1056
 	}
1057 1057
 	for {
1058 1058
 		// Read number of console events available
1059
-		tempBuffer := make([]INPUT_RECORD, MAX_INPUT_BUFFER)
1060
-		nr, err := readConsoleInputKey(uintptr(handle), tempBuffer)
1059
+		nr, err := readConsoleInputKey(uintptr(handle), inputEvents)
1061 1060
 		if nr == 0 {
1062
-			return nil, err
1061
+			return 0, err
1063 1062
 		}
1064 1063
 		if 0 < nr {
1065
-			retValue := make([]INPUT_RECORD, nr)
1066
-			for i := 0; i < nr; i++ {
1067
-				retValue[i] = tempBuffer[i]
1068
-			}
1069
-			return retValue, nil
1064
+			return nr, nil
1070 1065
 		}
1071 1066
 	}
1072 1067
 }
... ...
@@ -1086,32 +1091,19 @@ func getTranslatedKeyCodes(inputEvents []INPUT_RECORD, escapeSequence []byte) st
1086 1086
 }
1087 1087
 
1088 1088
 // ReadChars reads the characters from the given reader
1089
-func (term *WindowsTerminal) ReadChars(fd uintptr, w io.Reader, p []byte) (n int, err error) {
1090
-	n = 0
1091
-	for n < len(p) {
1092
-		select {
1093
-		case b := <-term.inputBuffer:
1094
-			p[n] = b
1095
-			n++
1096
-		default:
1097
-			// Read at least one byte read
1098
-			if n > 0 {
1099
-				return n, nil
1100
-			}
1101
-			inputEvents, _ := getAvailableInputEvents(fd)
1102
-			if inputEvents != nil {
1103
-				if len(inputEvents) == 0 && nil != err {
1104
-					return n, err
1105
-				}
1106
-				if len(inputEvents) != 0 {
1107
-					keyCodes := getTranslatedKeyCodes(inputEvents, term.inputEscapeSequence)
1108
-					for _, b := range []byte(keyCodes) {
1109
-						term.inputBuffer <- b
1110
-					}
1111
-				}
1112
-			}
1089
+func (term *WindowsTerminal) ReadChars(fd uintptr, r io.Reader, p []byte) (n int, err error) {
1090
+	for term.inputSize == 0 {
1091
+		nr, err := getAvailableInputEvents(fd, term.inputEvents)
1092
+		if nr == 0 && nil != err {
1093
+			return n, err
1094
+		}
1095
+		if nr > 0 {
1096
+			keyCodes := getTranslatedKeyCodes(term.inputEvents[:nr], term.inputEscapeSequence)
1097
+			term.inputSize = copy(term.inputBuffer, keyCodes)
1113 1098
 		}
1114 1099
 	}
1100
+	n = copy(p, term.inputBuffer[:term.inputSize])
1101
+	term.inputSize -= n
1115 1102
 	return n, nil
1116 1103
 }
1117 1104