*Problem Description* 

I’m running a simple TCP throughput benchmark using Go 1.24.6.
Both the client and server have abundant CPU, memory, and network 
resources, and no system-level limits (ulimits, NIC queues, CPU throttling, 
etc.) are in effect.

However, I’m observing an unexpected behavior:

*The throughput of each individual goroutine becomes higher when the 
overall client concurrency increases.*
Example: per-goroutine throughput at concurrency=5 < concurrency=10 < 
concurrency=15.

This is counterintuitive — I expect each goroutine's performance to remain 
roughly the same regardless of how many other goroutines are running.
*Test Setup* *Server* 

The server sends a fixed 64MiB random buffer to every client connection. It 
uses a 1 MiB write buffer.
*Client* 

The client spawns N concurrent goroutines (concurrency = 5, 10, 15...).
Each goroutine opens a TCP connection and reads until EOF using a 32 MiB 
buffer.
*Observed Behavior* 
   
   - 
   
   When running with 1 goroutine, the read time is *longer*.
   - 
   
   As I increase concurrency to 5, 10, 15... the *throughput of each 
   individual goroutine improves significantly*.
   - 
   
   This happens even though:
   - 
      
      CPU is not saturated
      - 
      
      Network is not saturated
      - 
      
      Disk is not involved
      - 
      
      Both machines have very high bandwidth (10 GbE+)
      
*Expected Behavior* 

Each goroutine should achieve similar throughput regardless of how many 
goroutines are running concurrently, assuming sufficient system resources.

*Test code*

1、server:

package main

 

import (

"bytes"

"fmt"

"math/rand"

"net"

"net/http"

_ "net/http/pprof"

"time"

"io"

)

 

const dataSize = 64 * 1024 * 1024 // 64 MiB

 

func main() {

go func() {

fmt.Println("pprof listening on :6060")

http.ListenAndServe("10.58.3.23:6060", nil)

}()

 

ln, err := net.Listen("tcp", "10.58.3.23:9090")

if err != nil {

panic(err)

}

fmt.Println("Server listening on :9090")

 

data := make([]byte, dataSize)

rand.Read(data)

 

for {

conn, err := ln.Accept()

if err != nil {

fmt.Println("Accept error:", err)

continue

}

go handleConn(conn, data)

}

}

 

func handleConn(conn net.Conn, data []byte) {

defer conn.Close()

 

fmt.Println("Client connected:", conn.RemoteAddr())

start := time.Now()

r := bytes.NewReader(data)

_, err := io.Copy(conn, r)

if err != nil {

fmt.Println("Write error:", err)

return

}

 

duration := time.Since(start)

fmt.Printf("Sent %d bytes to %v, duration: %v\n", dataSize, conn.RemoteAddr
(), duration)

}


*2、client code:*

package main

 

import (

"fmt"

"io"

"net"

"sync"

"time"

)

 

const concurrency = 4 

 

func main() {

var wg sync.WaitGroup

 

for i := 0; i < concurrency; i++ {

wg.Add(1)

go func(id int) {

defer wg.Done()

start := time.Now() 

conn, err := net.Dial("tcp", "10.58.3.23:9090")

if err != nil {

fmt.Printf("[Worker %d] Dial error: %v\n", id, err)

return

}

defer conn.Close()

buf := make([]byte, 64*1024*1024) // 1 MiB buffer

total := 0

for {

n, err := conn.Read(buf)

total += n

if err == io.EOF {

break

}

if err != nil {

fmt.Printf("[Worker %d] Read error: %v\n", id, err)

return

}

}

duration := time.Since(start)

fmt.Printf("[Worker %d] Finished reading %d bytes, duration: %v\n", id, 
total, duration)

}(i + 1)

}

 

wg.Wait()

fmt.Println("All goroutines completed")

}


-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/golang-nuts/f307dd0e-cc9d-434e-a452-8e367e987f3bn%40googlegroups.com.

Reply via email to