Goroutine Graphical I / O Scheduling

Golangs goroutines is a blocking I / O interface for goroutine (-programmer). Behind the scenes, the runtime uses some kind of blocking I / O to prevent the OS thread from being suspended, so that the runtime can run another goroutine on top of the OS thread while doing I / O.

When does the runtime account for the I / O execution so that it can port the goroutine?

To be clear, if I have net.TCPConn

which I am calling Write

on, when can I expect the goroutine to be ported?

conn, err := net.Dial("tcp", serverAddr)
conn.Write(buffer)
timestamp = time.Now()

      

That is, when can I expect a timestamp?

  • When was the buffer copied during golang runtime?
  • When was the buffer copied at runtime and into OS kernel space?
  • When was the buffer copied at runtime, kernel space and in addition to the NIC send buffer?
  • When is the buffer sent over the network / from the network adapter?
  • When the buffer was acknowledged on receipt, is the TCP stack stack?
+3


source to share


2 answers


You can look at the file https://github.com/golang/go/blob/master/src/net/fd_unix.go (recording function).

It mainly depends on free space in the socket buffer.

If there is enough space in the socket buffer to accommodate the size of your write operation, the data will be immediately written to the socket buffer. I think this matches your second answer. Also, the kernel can actually send a packet (or add it to the NIC queues), but it doesn't depend on the Go runtime.



If there is not enough space in the socket buffer to accommodate the entire write operation, only a portion of the data will be immediately written to the socket buffer. The call then blocks (via a runtime polling mechanism) until the kernel has made some space in the socket buffer (by sending some packets). As soon as some space is available and all data has been copied, the call will be unlocked.

Note that the timestamp is taken when the network packet has written the entire buffer in the socket buffer using a system call.

+3


source


The following article describes how netpoller works:

Whenever goroutine tries to read or write to the connection, the network code performs the operation until it receives such an error, and then call netpoller telling it to notify goroutine when it's ready to do I / O again ... Then a goroutine is assigned from the thread it is running on and another goroutine is started in its place.

When netpoller receives a notification from the OS that it can do I / O on a file descriptor, it will look at its internal data structure, see if there are any goroutines that are locked in that file, and notify them if there are any. Gorotin can retry the I / O operation that caused him to block and succeed. "



Thus, we conclude that the goroutine can be carried over when the underlying system call completes the write for the entire buffer. In the case of Linux, it looks like when the message was copied into the kernel space send buffer: Blocking sockets: when exactly does "send ()" return? This in turn is my second original "When the buffer was copied at runtime and into the OS kernel space "; also consistent with Didier Spezia's answer .

+2


source







All Articles