mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-22 18:06:52 +00:00
* Update package version * Update makefile targets * Update readme packages * Remaining old packages via rg/sd
101 lines
3 KiB
Go
101 lines
3 KiB
Go
// This is the entry point for the mlr executable.
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
"runtime/debug"
|
|
"runtime/pprof"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/johnkerl/miller/v6/pkg/entrypoint"
|
|
"github.com/pkg/profile" // for trace.out
|
|
)
|
|
|
|
func main() {
|
|
// For mlr --time
|
|
startTime := time.Now()
|
|
|
|
// Respect env $GOMAXPROCS, if provided, else set default.
|
|
haveSetGoMaxProcs := false
|
|
goMaxProcsString := os.Getenv("GOMAXPROCS")
|
|
if goMaxProcsString != "" {
|
|
goMaxProcs, err := strconv.Atoi(goMaxProcsString)
|
|
if err != nil {
|
|
runtime.GOMAXPROCS(goMaxProcs)
|
|
haveSetGoMaxProcs = true
|
|
}
|
|
}
|
|
if !haveSetGoMaxProcs {
|
|
// As of Go 1.16 this is the default anyway. For 1.15 and below we need
|
|
// to explicitly set this.
|
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
|
}
|
|
|
|
debug.SetGCPercent(500) // Empirical: See README-profiling.md
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CPU profiling
|
|
//
|
|
// We do this here, not in the command-line parser, since
|
|
// pprof.StopCPUProfile() needs to be called at the very end of everything.
|
|
// Putting this pprof logic into a go func running in parallel with main,
|
|
// and properly stopping the profile only when main ends via chan-sync,
|
|
// results in a zero-length pprof file.
|
|
//
|
|
// Please see README-profiling.md for more information.
|
|
|
|
if len(os.Args) >= 3 && os.Args[1] == "--cpuprofile" {
|
|
profFilename := os.Args[2]
|
|
handle, err := os.Create(profFilename)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, os.Args[0], ": ", "Could not start CPU profile: ", err)
|
|
return
|
|
}
|
|
defer handle.Close()
|
|
|
|
if err := pprof.StartCPUProfile(handle); err != nil {
|
|
fmt.Fprintln(os.Stderr, os.Args[0], ": ", "Could not start CPU profile: ", err)
|
|
return
|
|
}
|
|
defer pprof.StopCPUProfile()
|
|
|
|
fmt.Fprintf(os.Stderr, "CPU profile started.\n")
|
|
defer fmt.Fprintf(os.Stderr, "CPU profile finished.\ngo tool pprof -http=:8080 %s\n", profFilename)
|
|
}
|
|
|
|
if len(os.Args) >= 2 && os.Args[1] == "--traceprofile" {
|
|
defer profile.Start(profile.TraceProfile, profile.ProfilePath(".")).Stop()
|
|
defer fmt.Fprintf(os.Stderr, "go tool trace trace.out\n")
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// This will obtain os.Args and go from there. All the usual contents of
|
|
// main() are put into this package for ease of testing.
|
|
mainReturn := entrypoint.Main()
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Timing
|
|
//
|
|
// The system 'time' command is built-in, of course but it's nice to have
|
|
// simply wall-time without the real/user/sys distinction. Also, making
|
|
// this a Miller built-in is nice for Windows.
|
|
if mainReturn.PrintElapsedTime {
|
|
endTime := time.Now()
|
|
startNanos := startTime.UnixNano()
|
|
endNanos := endTime.UnixNano()
|
|
seconds := float64(endNanos-startNanos) / 1e9
|
|
fmt.Fprintf(os.Stderr, "%.6f", seconds)
|
|
for _, arg := range os.Args {
|
|
if strings.Contains(arg, " ") || strings.Contains(arg, "\t") {
|
|
fmt.Fprintf(os.Stderr, " '%s'", arg)
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, " %s", arg)
|
|
}
|
|
}
|
|
fmt.Fprintf(os.Stderr, "\n")
|
|
}
|
|
}
|