简体   繁体   中英

Excessive CPU usage on Golang stdin loop

I have a golang app which needs to listen for input on stdin - not as a command line utility but to keep running and listening. The following code, slightly edited down, works but has very high CPU load when 'idle' - and I am not sure why - nor clear how this could be done better. So I need the same functionality without the CPU load! (this is part of an authentication handler for ejabberd)

bioIn := bufio.NewReader(os.Stdin)
bioOut := bufio.NewWriter(os.Stdout)

var err error
var success bool
var length uint16
var result uint16

for {
    binary.Read(bioIn, binary.BigEndian, &length)

    buf := make([]byte, length)

    r, _ := bioIn.Read(buf)
    if r == 0 {
        continue
    }

    if err == nil {
        data := strings.Split(string(buf), ":")
        // I have code to handle the incoming data here...
    } else {
        success = false
    }

    length = 2
    binary.Write(bioOut, binary.BigEndian, &length)

    if success != true {
        result = 0
    } else {
        result = 1
    }

    binary.Write(bioOut, binary.BigEndian, &result)
    bioOut.Flush()
}

ANSWER:

I added a short sleep as suggested and this has worked a charm; didn't need to be long and no noticeable impact on the authentication the service is providing. With the reassurance incoming data is buffered this is perfect fix. Thanks all.

r, _ := bioIn.Read(buf)
    if r == 0 {
        time.Sleep(25 * time.Millisecond)
        continue
}

In this part of your code:

 r, _ := bioIn.Read(buf)
 if r == 0 {
      continue
  }

You check for a return value of 0, which means EOF. ie the input stream has ended/terminated. Once stdin is terminated, it's not going to come back. So you have an endless loop here. it'll just spin around on this test having bioIn.Read() return 0 every time.

You can't really do much more than quit/exit at that point, stdin doesn't have any more data for you, ever.

Note that your code also discard the error returned from bioIn.Read() - don't do that, deal with errors - and you would have discovered the cause for yourself in this case.

You have a tight infinite loop, which will always take as much CPU as the OS will allow. You are always checking to see if there's any input and (in your sample code) you never wait for new input - you just continuously poll stdin to see if there is any. You should probably use time.Sleep() to wait some time between each check.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM