Hi,
I've been recently experimenting with system pipes performance using Go, 
trying to measure how fast I could read from STDIN to a buffer, then do 
something with it.

During that experiment I noticed a significant throughput degradation when 
reading into the same buffer vs different (pre-allocated) buffers.

To make things more interesting, this performance degradation seems to 
happen on my Linux system only, when done in a Mac laptop throughput is 
consistent regardless of the count of buffers I am writing to which is what 
I was initially expecting.

To remove throughput variance from cache misses, I've pinned both processes 
to the same virtual core.

My question is why is this happening? and, is there a way to avoid it?

Below code snipped and command lines
---------------------------------------

$ taskset 0x1 cat 10GiB | taskset 0x1 ./stdin-to-buffer -buffer-count=*1*
Start time: 2023-03-05T12:26:21-08:00
Total bytes read: 10737418240
Chunks: 10240
*Throughput: 2903 MiB/s*
Total time: 3.527284627s
Finish time: 2023-03-05T12:26:25-08:00

$ taskset 0x1 cat 10GiB | taskset 0x1 ./stdin-to-buffer -buffer-count=*25*
Start time: 2023-03-05T12:26:29-08:00
Total bytes read: 10737418240
Chunks: 10240
*Throughput: 2531 MiB/s*
Total time: 4.045169972s
Finish time: 2023-03-05T12:26:34-08:00

$ taskset 0x1 cat 10GiB | taskset 0x1 ./stdin-to-buffer -buffer-count=*50*
Start time: 2023-03-05T12:26:39-08:00
Total bytes read: 10737418240
Chunks: 10240
*Throughput: 2215 MiB/s*
Total time: 4.623220632s
Finish time: 2023-03-05T12:26:43-08:00

$ taskset 0x1 cat 10GiB | taskset 0x1 ./stdin-to-buffer -buffer-count=*150*
Start time: 2023-03-05T12:26:49-08:00
Total bytes read: 10737418240
Chunks: 10240
*Throughput: 1916 MiB/s*
Total time: 5.344739086s
Finish time: 2023-03-05T12:26:54-08:00

$ taskset 0x1 cat 10GiB | taskset 0x1 ./stdin-to-buffer -buffer-count=*250*
Start time: 2023-03-05T12:26:59-08:00
Total bytes read: 10737418240
Chunks: 10240
*Throughput: 1732 MiB/s*
Total time: 5.910793462s
Finish time: 2023-03-05T12:27:05-08:00

$ taskset 0x1 cat 10GiB | taskset 0x1 ./stdin-to-buffer -buffer-count=*500*
Start time: 2023-03-05T12:27:13-08:00
Total bytes read: 10737418240
Chunks: 10240
*Throughput: 1757 MiB/s*
Total time: 5.827294797s
Finish time: 2023-03-05T12:27:19-08:00

---------------------------------------
Code for stdin-to-buffer.go follows.
---------------------------------------
package main

import (
"bytes"
"flag"
"fmt"
"io"
"log"
"math"
"os"
"time"
)

var (
    bufCount = flag.Int("buffer-count", 8, "The number of buffers")
    bufSize = flag.Int("buffer-size-bytes", 1048576 /*1MiB*/, "The buffer 
size in bytes")
)

func main() {
    flag.Parse()

    var nBytes, nChunks int

    bufPool := make([][]byte, *bufCount)
    for i := 0; i < *bufCount; i++ {
        bufPool[i] = make([]byte, *bufSize)
    }

    var startTime = time.Now()
    var loopIteration = -1

loop:
    for {
        loopIteration++
        buf := bufPool[loopIteration%*bufCount]
        n, err := io.ReadFull(os.Stdin, buf)

        if n > 0 {
            nChunks++
            nBytes += n
        }

        switch err {
            case nil:
                continue
            case io.EOF, io.ErrUnexpectedEOF:
                break loop
        }
        log.Fatal(err)
    }

    finishTime := time.Now()
    totalTime := finishTime.Sub(startTime)
    fmt.Fprintf(os.Stderr, "Start time: %v\n",     startTime.Format(time.
RFC3339))
    fmt.Fprintf(os.Stderr, "Total bytes read: %v\n", nBytes)
    fmt.Fprintf(os.Stderr, "Chunks: %v\n", nChunks)
    fmt.Fprintf(os.Stderr, "Throughput: %v MiB/s\n",     math.Round(float64(
nBytes)/math.Pow(1024, 2)/totalTime.Seconds()))
    fmt.Fprintf(os.Stderr, "Total time: %v\n", totalTime)
    fmt.Fprintf(os.Stderr, "Finish time: %v\n",     finishTime.Format(time.
RFC3339))
}

-- 
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 golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/25b73eb9-5c40-4070-b3c1-3a63ce6ccf6dn%40googlegroups.com.

Reply via email to