Ver Fonte

Reduce memory allocation and remove channels

Signed-off-by: Sachin Joshi <sachin_jayant_joshi@hotmail.com>
Sachin Joshi há 10 anos atrás
pai
commit
816d602059
2 ficheiros alterados com 35 adições e 43 exclusões
  1. 4 4
      docker/docker.go
  2. 31 39
      pkg/term/winconsole/console_windows.go

+ 4 - 4
docker/docker.go

@@ -26,15 +26,15 @@ const (
 )
 
 func main() {
+	if reexec.Init() {
+		return
+	}
+
 	// Set terminal emulation based on platform as required.
 	stdout, stderr, stdin := term.StdStreams()
 
 	initLogging(stderr)
 
-	if reexec.Init() {
-		return
-	}
-
 	flag.Parse()
 	// FIXME: validate daemon flags here
 

+ 31 - 39
pkg/term/winconsole/console_windows.go

@@ -83,6 +83,7 @@ const (
 
 	ANSI_MAX_CMD_LENGTH = 256
 
+	MAX_INPUT_EVENTS = 128
 	MAX_INPUT_BUFFER = 1024
 	DEFAULT_WIDTH    = 80
 	DEFAULT_HEIGHT   = 24
@@ -195,15 +196,18 @@ type (
 type WindowsTerminal struct {
 	outMutex            sync.Mutex
 	inMutex             sync.Mutex
-	inputBuffer         chan byte
+	inputBuffer         []byte
+	inputSize           int
+	inputEvents         []INPUT_RECORD
 	screenBufferInfo    *CONSOLE_SCREEN_BUFFER_INFO
 	inputEscapeSequence []byte
 }
 
 func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
 	handler := &WindowsTerminal{
-		inputBuffer:         make(chan byte, MAX_INPUT_BUFFER),
+		inputBuffer:         make([]byte, MAX_INPUT_BUFFER),
 		inputEscapeSequence: []byte(KEY_ESC_CSI),
+		inputEvents:         make([]INPUT_RECORD, MAX_INPUT_EVENTS),
 	}
 
 	// Save current screen buffer info
@@ -218,6 +222,8 @@ func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
 
 	// Set the window size
 	SetWindowSize(uintptr(handle), DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_HEIGHT)
+	buffer = make([]CHAR_INFO, screenBufferInfo.MaximumWindowSize.X*screenBufferInfo.MaximumWindowSize.Y)
+
 	if IsTerminal(os.Stdout.Fd()) {
 		stdOut = &terminalWriter{
 			wrappedWriter: os.Stdout,
@@ -427,6 +433,8 @@ func getNumberOfChars(fromCoord COORD, toCoord COORD, screenSize COORD) uint32 {
 	return 0
 }
 
+var buffer []CHAR_INFO
+
 func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (bool, uint32, error) {
 	var writeRegion SMALL_RECT
 	writeRegion.Top = fromCoord.Y
@@ -439,14 +447,13 @@ func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoor
 	height := toCoord.Y - fromCoord.Y + 1
 	size := width * height
 	if size > 0 {
-		buffer := make([]CHAR_INFO, size)
-		for i := 0; i < len(buffer); i++ {
+		for i := 0; i < int(size); i++ {
 			buffer[i].UnicodeChar = WCHAR(fillChar)
 			buffer[i].Attributes = attributes
 		}
 
 		// Write to buffer
-		r, err := writeConsoleOutput(fileDesc, buffer, windowSize, COORD{X: 0, Y: 0}, &writeRegion)
+		r, err := writeConsoleOutput(fileDesc, buffer[:size], windowSize, COORD{X: 0, Y: 0}, &writeRegion)
 		if !r {
 			if err != nil {
 				return false, 0, err
@@ -914,6 +921,9 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
 
 // WriteChars writes the bytes to given writer.
 func (term *WindowsTerminal) WriteChars(fd uintptr, w io.Writer, p []byte) (n int, err error) {
+	if len(p) == 0 {
+		return 0, nil
+	}
 	return w.Write(p)
 }
 
@@ -1049,24 +1059,19 @@ func mapKeystokeToTerminalString(keyEvent *KEY_EVENT_RECORD, escapeSequence []by
 
 // getAvailableInputEvents polls the console for availble events
 // The function does not return until at least one input record has been read.
-func getAvailableInputEvents(fd uintptr) (inputEvents []INPUT_RECORD, err error) {
+func getAvailableInputEvents(fd uintptr, inputEvents []INPUT_RECORD) (n int, err error) {
 	handle := syscall.Handle(fd)
 	if nil != err {
-		return nil, err
+		return 0, err
 	}
 	for {
 		// Read number of console events available
-		tempBuffer := make([]INPUT_RECORD, MAX_INPUT_BUFFER)
-		nr, err := readConsoleInputKey(uintptr(handle), tempBuffer)
+		nr, err := readConsoleInputKey(uintptr(handle), inputEvents)
 		if nr == 0 {
-			return nil, err
+			return 0, err
 		}
 		if 0 < nr {
-			retValue := make([]INPUT_RECORD, nr)
-			for i := 0; i < nr; i++ {
-				retValue[i] = tempBuffer[i]
-			}
-			return retValue, nil
+			return nr, nil
 		}
 	}
 }
@@ -1086,32 +1091,19 @@ func getTranslatedKeyCodes(inputEvents []INPUT_RECORD, escapeSequence []byte) st
 }
 
 // ReadChars reads the characters from the given reader
-func (term *WindowsTerminal) ReadChars(fd uintptr, w io.Reader, p []byte) (n int, err error) {
-	n = 0
-	for n < len(p) {
-		select {
-		case b := <-term.inputBuffer:
-			p[n] = b
-			n++
-		default:
-			// Read at least one byte read
-			if n > 0 {
-				return n, nil
-			}
-			inputEvents, _ := getAvailableInputEvents(fd)
-			if inputEvents != nil {
-				if len(inputEvents) == 0 && nil != err {
-					return n, err
-				}
-				if len(inputEvents) != 0 {
-					keyCodes := getTranslatedKeyCodes(inputEvents, term.inputEscapeSequence)
-					for _, b := range []byte(keyCodes) {
-						term.inputBuffer <- b
-					}
-				}
-			}
+func (term *WindowsTerminal) ReadChars(fd uintptr, r io.Reader, p []byte) (n int, err error) {
+	for term.inputSize == 0 {
+		nr, err := getAvailableInputEvents(fd, term.inputEvents)
+		if nr == 0 && nil != err {
+			return n, err
+		}
+		if nr > 0 {
+			keyCodes := getTranslatedKeyCodes(term.inputEvents[:nr], term.inputEscapeSequence)
+			term.inputSize = copy(term.inputBuffer, keyCodes)
 		}
 	}
+	n = copy(p, term.inputBuffer[:term.inputSize])
+	term.inputSize -= n
 	return n, nil
 }