Skip to content

Instantly share code, notes, and snippets.

@tidwall
Created March 13, 2019 17:46
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tidwall/b119d907d0961a3ca70026142929a2ea to your computer and use it in GitHub Desktop.
Save tidwall/b119d907d0961a3ca70026142929a2ea to your computer and use it in GitHub Desktop.
Go 1.12 network slowdown on Darwin
package main
import (
"fmt"
"io"
"log"
"net"
"os"
"sync"
"sync/atomic"
"time"
)
func main() {
switch {
case len(os.Args) > 1 && os.Args[1] == "bench":
bench()
case len(os.Args) > 1 && os.Args[1] == "server":
server()
default:
fmt.Fprintf(os.Stderr, "usage: <command> server|bench\n")
os.Exit(1)
}
}
func server() {
log.Printf("echo server started\n")
os.RemoveAll("socket")
ln, err := net.Listen("unix", "socket")
if err != nil {
log.Fatal(err)
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
go func(conn net.Conn) {
defer conn.Close()
var packet [256]byte
for {
n, err := conn.Read(packet[:])
if err != nil {
return
}
conn.Write(packet[:n])
}
}(conn)
}
}
func bench() {
c := 50
n := 100000
log.Printf("echo benchmark connecting %d clients\n", c)
start := time.Now()
var total int32
var wg sync.WaitGroup
wg.Add(c)
for i := 0; i < c; i++ {
go func() {
defer wg.Done()
conn, err := net.Dial("unix", "socket")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
packet := []byte("ping\n")
for i := 0; i < n/c; i++ {
conn.Write(packet)
if _, err := io.ReadFull(conn, packet); err != nil {
log.Fatal(err)
}
if atomic.AddInt32(&total, 1)%3131 == 0 {
fmt.Printf("\r%.0f ops/sec ",
float64(total)/time.Since(start).Seconds())
}
}
}()
}
wg.Wait()
fmt.Printf("\r%.0f ops/sec\n",
float64(total)/time.Since(start).Seconds())
}
@tidwall
Copy link
Author

tidwall commented Mar 13, 2019

Basic networking is a lot slower on Go 1.12 Darwin

go version arch op/sec
1.11.5 darwin 265,409
1.12 darwin 16,509
1.11.5 linux 331,180
1.12 linux 359,625

Reproduce

Download go1.11.5 and go1.12

$ go get golang.org/dl/go1.11.5
$ go1.11.5 download
$ go get golang.org/dl/go1.12
$ go1.12 download

go1.11.5-darwin

Open terminal #1 (server)

$ go1.11.5 run main.go server
2019/03/13 10:50:02 echo server started

Open terminal #2 (bench)

$ go1.11.5 run main.go bench
2019/03/13 10:50:51 echo benchmark using 50 clients
265409 ops/sec

go1.12-darwin

Open terminal #1 (server)

$ go1.12 run main.go server
2019/03/13 10:50:02 echo server started

Open terminal #2 (bench)

$ go1.12 run main.go bench
2019/03/13 10:50:51 echo benchmark using 50 clients
16509 ops/sec

go1.11.5-linux

Open terminal #1 (server)

$ go1.11.5 run main.go server
2019/03/13 10:50:02 echo server started

Open terminal #2 (bench)

$ go1.11.5 run main.go bench
2019/03/13 10:50:51 echo benchmark using 50 clients
331180 ops/sec

go1.12-linux

Open terminal #1 (server)

$ go1.12 run main.go server
2019/03/13 11:17:30 echo server started

Open terminal #2 (bench)

$ go1.12 run main.go bench
2019/03/13 11:17:37 echo benchmark using 50 clients
359625 ops/sec

@s32x
Copy link

s32x commented Mar 13, 2019

$ go1.11.5 run main.go bench
2019/03/13 11:33:42 echo benchmark connecting 50 clients
267517 ops/sec
$ go1.12 run main.go bench
2019/03/13 11:33:55 echo benchmark connecting 50 clients
95068 ops/sec

@tidwall
Copy link
Author

tidwall commented Mar 18, 2019

Just tested with Go 1.12.1 on macOS Mojave 10.14.3.

go version arch op/sec
1.12.1 darwin 15,590

@valinurovam
Copy link

valinurovam commented Apr 16, 2019

Have same issue

go version arch op/sec
both go1.12.4 darwin 63431 ops/sec
both go1.11.5 darwin 204351 ops/sec
server 1.11.5 + client 1.12.4 darwin 114049 ops/sec
server 1.12.4 + client 1.11.5 darwin 115997 ops/sec

Looks like in 1.12.4 runtime spent much time to scheduling and less for networking

top20 from pprof for 1.11.5

Showing top 20 nodes out of 32
      flat  flat%   sum%        cum   cum%
     0.88s 74.58% 74.58%      0.88s 74.58%  syscall.Syscall
     0.10s  8.47% 83.05%      0.10s  8.47%  runtime.pthread_cond_signal
     0.08s  6.78% 89.83%      0.08s  6.78%  runtime.kevent
     0.05s  4.24% 94.07%      0.05s  4.24%  runtime.pthread_cond_wait
     0.03s  2.54% 96.61%      0.03s  2.54%  runtime.freedefer
     0.02s  1.69% 98.31%      0.10s  8.47%  runtime.netpoll
     0.01s  0.85% 99.15%      0.01s  0.85%  runtime.kevent_trampoline
     0.01s  0.85%   100%      0.01s  0.85%  runtime.nanotime
         0     0%   100%      0.68s 57.63%  internal/poll.(*FD).Read
         0     0%   100%      0.23s 19.49%  internal/poll.(*FD).Write
         0     0%   100%      0.91s 77.12%  main.server.func2
         0     0%   100%      0.68s 57.63%  net.(*conn).Read
         0     0%   100%      0.23s 19.49%  net.(*conn).Write
         0     0%   100%      0.68s 57.63%  net.(*netFD).Read
         0     0%   100%      0.23s 19.49%  net.(*netFD).Write
         0     0%   100%      0.01s  0.85%  runtime.asmcgocall
         0     0%   100%      0.03s  2.54%  runtime.deferreturn
         0     0%   100%      0.26s 22.03%  runtime.findrunnable
         0     0%   100%      0.10s  8.47%  runtime.injectglist
         0     0%   100%      0.26s 22.03%  runtime.mcall

same for 1.12.4

Showing top 20 nodes out of 39
      flat  flat%   sum%        cum   cum%
     1.93s 39.55% 39.55%      1.93s 39.55%  runtime.pthread_cond_wait
     0.97s 19.88% 59.43%         1s 20.49%  syscall.syscall
     0.76s 15.57% 75.00%      0.76s 15.57%  runtime.pthread_cond_signal
     0.69s 14.14% 89.14%      0.69s 14.14%  runtime.freedefer
     0.13s  2.66% 91.80%      0.13s  2.66%  runtime.pthread_mutex_unlock
     0.12s  2.46% 94.26%      0.22s  4.51%  runtime.netpoll
     0.09s  1.84% 96.11%      0.09s  1.84%  runtime.kevent
     0.04s  0.82% 96.93%      0.04s  0.82%  runtime.usleep
     0.02s  0.41% 97.34%      1.72s 35.25%  main.server.func2
     0.01s   0.2% 97.54%      0.03s  0.61%  runtime.exitsyscall
     0.01s   0.2% 97.75%      1.95s 39.96%  runtime.semasleep
     0.01s   0.2% 97.95%      0.60s 12.30%  syscall.read
         0     0% 97.95%      0.98s 20.08%  internal/poll.(*FD).Read
         0     0% 97.95%      0.71s 14.55%  internal/poll.(*FD).Write
         0     0% 97.95%      0.98s 20.08%  net.(*conn).Read
         0     0% 97.95%      0.71s 14.55%  net.(*conn).Write
         0     0% 97.95%      0.98s 20.08%  net.(*netFD).Read
         0     0% 97.95%      0.71s 14.55%  net.(*netFD).Write
         0     0% 97.95%      0.69s 14.14%  runtime.deferreturn
         0     0% 97.95%      0.85s 17.42%  runtime.entersyscallblock_handoff

@c1982
Copy link

c1982 commented May 16, 2019

Still continue in 1.12.5

go 1.11     darwin  268.093 ops/sec
go 1.12.5   darwin  71.273 ops/sec 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment