xvertile
xvertile

Reputation: 17

Golang runtime/internal/syscall.Syscall6 consuming large amount of CPU

I have a TCP based proxy server running on Ubuntu 22.04.4 LTS. It performs really well but when analyzing with https://github.com/google/pprof it gives me this output:

      flat  flat%   sum%        cum   cum%
     4.97s 54.98% 54.98%      4.97s 54.98%  runtime/internal/syscall.Syscall6
     0.95s 10.51% 65.49%      0.95s 10.51%  runtime.(*lfstack).pop
     0.49s  5.42% 70.91%      0.98s 10.84%  runtime.stealWork
     0.26s  2.88% 73.78%      0.26s  2.88%  runtime.(*lfstack).push
     0.25s  2.77% 76.55%      0.25s  2.77%  runtime.pMask.read (inline)
     0.23s  2.54% 79.09%      0.23s  2.54%  runtime.futex
     0.20s  2.21% 81.31%      0.20s  2.21%  runtime.(*randomEnum).next (inline)
     0.09s     1% 82.30%      0.09s     1%  runtime.nanotime (inline)
     0.08s  0.88% 83.19%      0.09s     1%  runtime.findObject
     0.07s  0.77% 83.96%      0.07s  0.77%  runtime.(*mspan).base

The majority of the time / CPU is on runtime/internal/syscall.Syscall6 when I try and find more details about this I cannot find anything on what it truly is. Here is the SVG output: SVG ouput pprof

can anyone give me some more insights on what the Syscall6 is?

I can provide some psuedo code:

func main() {
    listener, err := net.Listen("tcp", fmt.Sprintf("%v:%v", config.Cfg.Server.Host, config.Cfg.Server.Port))
    if err != nil {
        logging.Logger.Error().
            Err(err).
            Msg("An unexpected error has occurred")
        return
    }

    for {
        c, err := listener.Accept()
        if err != nil {
            logging.Logger.Error().
                Err(err).
                Msg("An unexpected error has occurred")
            return
        }
        go handlers.Handle(c)
    }
}

It then does some simple auth checking and then it processes the request and writes back the response.

func routehttps(c net.Conn, r *http.Request) error {
    dialer := net.Dialer{}
    log.Print("Dialing HTTPS connection")
    conn, err := dialer.Dial("tcp", r.Host)
    if err != nil {
        return err
    }

    defer conn.Close()

    response := &http.Response{
        Status:        "200 OK",
        StatusCode:    200,
        Proto:         "HTTP/1.1",
        ProtoMajor:    1,
        ProtoMinor:    1,
        Body:          ioutil.NopCloser(strings.NewReader("")),
        ContentLength: 0,
    }

    if err := response.Write(c); err != nil {
        return err
    }

    go io.Copy(conn, c)
    if _, err := io.Copy(c, conn); err != nil {
        return err
    }

    return nil
}

I cannot find any traces of the Syscall6 is this related to the TCP sockets itself?

I tried different variotions on my dialer with socket options but non made a difference.

Upvotes: 0

Views: 1014

Answers (1)

xvertile
xvertile

Reputation: 17

So I solved the issue via using a io.CopyBuffer

// Golang program to illustrate the usage of 
// io.CopyBuffer() function 
  
// Including main package 
package main 
  
// Importing fmt, io, os, and strings 
import ( 
    "fmt"
    "io"
    "os"
    "strings"
) 
  
// Calling main 
func main() { 
  
    // Defining source 
    src := strings.NewReader("GfG\n") 
  
    // Defining destination using Stdout 
    dst := os.Stdout 
  
    // Defining buffer of length one using 
    // make keyword 
    buffer := make([]byte, 1) 
  
    // Calling CopyBuffer method with its parameters 
    bytes, err := io.CopyBuffer(dst, src, buffer) 
  
    // If error is not nil then panics 
    if err != nil { 
        panic(err) 
    } 
  
    // Prints output 
    fmt.Printf("The number of bytes are: %d\n", bytes) 
} 

https://www.geeksforgeeks.org/io-copybuffer-function-in-golang-with-examples/

Upvotes: -1

Related Questions