golang tcp 서버를 구현하려고합니다. 동시성이 만족 스럽지만 CPU 사용량이 너무 높습니다 (동시성은 15W +/s이지만 CPU 사용량은 24 코어 Linux 머신에서 약 800 %입니다) . 동시에 C++ tcp 서버는 비슷한 동시성 (libevent 사용)으로 약 200 %의 사용률을 보이고 있습니다.golang tcp 서버에서 CPU 사용을 줄이려면 어떻게해야합니까?
다음 코드는 golang의 데모입니다 :
func main() {
listen, err := net.Listen("tcp", "0.0.0.0:17379")
if err != nil {
fmt.Errorf(err.Error())
}
go acceptClient(listen)
var channel2 = make(chan bool)
<-channel2
}
func acceptClient(listen net.Listener) {
for {
sock, err := listen.Accept()
if err != nil {
fmt.Errorf(err.Error())
}
tcp := sock.(*net.TCPConn)
tcp.SetNoDelay(true)
var channel = make(chan bool, 10)
go read(channel, sock.(*net.TCPConn))
go write(channel, sock.(*net.TCPConn))
}
}
func read(channel chan bool, sock *net.TCPConn) {
count := 0
for {
var buf = make([]byte, 1024)
n, err := sock.Read(buf)
if err != nil {
close(channel)
sock.CloseRead()
return
}
count += n
x := count/58
count = count % 58
for i := 0; i < x; i++ {
channel <- true
}
}
}
func write(channel chan bool, sock *net.TCPConn) {
buf := []byte("+OK\r\n")
defer func() {
sock.CloseWrite()
recover()
}()
for {
_, ok := <-channel
if !ok {
return
}
_, writeError := sock.Write(buf)
if writeError != nil {
return
}
}
}
그리고 멀티 클라이언트와 레디 스 벤치 마크하여 TCP 서버를 테스트 : 나는 또한에 의해 내 golang 코드를 분석
redis-benchmark -h 10.100.45.2 -p 17379 -n 1000 -q script load "redis.call('set','aaa','aaa')"
pprof, 그것은 syscall에 많은 시간을 CPU 비용이라고합니다 : enter image description here
아마도 코드 검토에 더 적합 할 것입니다. 몇 가지 생각 : 당신은 필요 이상으로 더 많은 채널을 사용하고 있으며, 소켓 유형 어설 션 –
에 대한 메신저를 놓치고있다. (나는 단지 수면을 추가 할 것을 제안 할 수있다.). ml에 게시 하시겠습니까? https://groups.google.com/forum/#!forum/golang-nuts –
io 용으로 시스템 콜에 소비되는 대부분의 시간은 예상 한 것입니다. 당신은 많은 쓰레기를 만들고 있습니다, 아마도 GC가 여분의 시간을 차지하고 있습니다. Go 프로그램은 아마도 더 많은 일을하고있을 것이기 때문에 총 CPU 사용량은 Go 프로그램에서 더 높을 것으로 예상되지만 처리량을 상당히 가깝게 얻을 수 있어야합니다. – JimB