masterzen / winrm

Command-line tool and library for Windows remote command execution in Go
Apache License 2.0
425 stars 129 forks source link

stdin io.Copy is too slow #141

Open BZValoche opened 1 year ago

BZValoche commented 1 year ago

Hi, My use case : I sent a huge stdin to a powershell in order to transfer a file. I send a base64 stream which is decoded on the fly at destination and outputed to a file. In RunWithContextWithInput(...), io.Copy(cmd.String, stdin) is just fine as long as everything is inlined properly by the compiler. But in my case, I want to have some information during the copy, so I use a struct of my own to have some feedback:

type ProgressReader struct {
    io.Reader
    Report func(int, error)
}
func (pr *ProgressReader) Read(p []bye) (n int, err error) {
    n, err := pr.Reader.Read(p)
    if pr.Report != nil {
        pr.Report(n, err)
    }
}

Using this, I get a 3 to 4 performance factor decrease, which is huge. All because the Read function cannot be inlined anymore. io.Copy(...) used 32K buffers. By replacing the io.Copy(...) by io.CopyBuffer(...) with larger buffer size than 32K, the performance is the same than when not using my ProgressReader. So my suggestion is to add an optional bufferSize parameter to the RunWithContextInput function, and use io.CopyBuffer is the parameter is provided.