Skip to content

Commit 69689fa

Browse files
committed
perf: 优化下et模式
1 parent 672437b commit 69689fa

File tree

3 files changed

+58
-4
lines changed

3 files changed

+58
-4
lines changed

core/syscall_unix.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,11 @@ func GetFdFromConn(c net.Conn) (newFd int, err error) {
7070
func duplicateSocket(socketFD int) (int, error) {
7171
return unix.Dup(socketFD)
7272
}
73+
74+
func GetSendBufferSize(fd int) (int, error) {
75+
size, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_SNDBUF)
76+
if err != nil {
77+
return 0, err
78+
}
79+
return size, nil
80+
}

core/syscall_windows.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"net"
88
"syscall"
9+
"unsafe"
910
)
1011

1112
func Write(fd int, p []byte) (n int, err error) {
@@ -47,3 +48,25 @@ func GetFdFromConn(conn net.Conn) (fd int, err error) {
4748
// 获取文件描述符
4849
return int(file.Fd()), nil
4950
}
51+
52+
func GetSendBufferSize(fd int) (int, error) {
53+
// Convert fd to windows Handle
54+
handle := syscall.Handle(fd)
55+
56+
// Use getsockopt to get send buffer size
57+
var size int32
58+
var length int32 = 4 // size of int32
59+
60+
// Call getsockopt with SOL_SOCKET and SO_SNDBUF
61+
err := syscall.Getsockopt(
62+
handle,
63+
syscall.SOL_SOCKET,
64+
syscall.SO_SNDBUF,
65+
(*byte)(unsafe.Pointer(&size)),
66+
&length,
67+
)
68+
if err != nil {
69+
return 0, err
70+
}
71+
return int(size), nil
72+
}

multi_event_loops.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,33 @@ func (e *MultiEventLoop) doRead(c *Conn, rbuf []byte) {
215215
handleData(c, &e.options, rbuf[:n])
216216
}
217217

218-
if e.options.triggerType == core.TriggerTypeLevel {
219-
if n < len(rbuf) {
220-
break
221-
}
218+
// https://man7.org/linux/man-pages/man7/epoll.7.html
219+
// Do I need to continuously read/write a file descriptor until
220+
// EAGAIN when using the EPOLLET flag (edge-triggered behavior)?
221+
222+
// Receiving an event from epoll_wait(2) should suggest to you
223+
// that such file descriptor is ready for the requested I/O
224+
// operation. You must consider it ready until the next
225+
// (nonblocking) read/write yields EAGAIN. When and how you will
226+
// use the file descriptor is entirely up to you.
227+
228+
// For packet/token-oriented files (e.g., datagram socket,
229+
// terminal in canonical mode), the only way to detect the end of
230+
// the read/write I/O space is to continue to read/write until
231+
// EAGAIN.
232+
233+
// For stream-oriented files (e.g., pipe, FIFO, stream socket),
234+
// the condition that the read/write I/O space is exhausted can
235+
// also be detected by checking the amount of data read from /
236+
// written to the target file descriptor. For example, if you
237+
// call read(2) by asking to read a certain amount of data and
238+
// read(2) returns a lower number of bytes, you can be sure of
239+
// having exhausted the read I/O space for the file descriptor.
240+
// The same is true when writing using write(2). (Avoid this
241+
// latter technique if you cannot guarantee that the monitored
242+
// file descriptor always refers to a stream-oriented file.)
243+
if n < len(rbuf) {
244+
break
222245
}
223246
}
224247
}

0 commit comments

Comments
 (0)