diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 6239219..9acf314 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -21,13 +21,13 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.22.x + go-version: 1.23.x - uses: actions/checkout@v2 - name: golangci-lint - uses: golangci/golangci-lint-action@v4.0.0 + uses: golangci/golangci-lint-action@v6.1.0 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.56.2 + version: v1.61.0 # Optional: working directory, useful for monorepos # working-directory: somedir diff --git a/.github/workflows/gorelease.yml b/.github/workflows/gorelease.yml index 6356a9d..c031db4 100644 --- a/.github/workflows/gorelease.yml +++ b/.github/workflows/gorelease.yml @@ -9,7 +9,7 @@ concurrency: cancel-in-progress: true env: - GO_VERSION: 1.22.x + GO_VERSION: 1.23.x jobs: gorelease: runs-on: ubuntu-latest diff --git a/.github/workflows/release-assets.yml b/.github/workflows/release-assets.yml index 14c61b7..a1a991e 100644 --- a/.github/workflows/release-assets.yml +++ b/.github/workflows/release-assets.yml @@ -8,7 +8,7 @@ on: - created env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GO_VERSION: 1.22.x + GO_VERSION: 1.23.x LINUX_AMD64_BUILD_OPTIONS: '-tags cgo_zstd' GOAMD64: v3 jobs: diff --git a/.github/workflows/test-unit.yml b/.github/workflows/test-unit.yml index 9b6e93d..41ae308 100644 --- a/.github/workflows/test-unit.yml +++ b/.github/workflows/test-unit.yml @@ -21,7 +21,7 @@ jobs: test: strategy: matrix: - go-version: [ 1.20.x, 1.21.x, 1.22.x ] + go-version: [ 1.21.x, 1.22.x, 1.23.x ] runs-on: ubuntu-latest steps: - name: Install Go stable diff --git a/.golangci.yml b/.golangci.yml index 43850cc..a3422c2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,38 +25,32 @@ linters: enable-all: true disable: - lll - - maligned - gochecknoglobals - gomnd - wrapcheck - paralleltest - forbidigo - - exhaustivestruct - - interfacer # deprecated - forcetypeassert - - scopelint # deprecated - - ifshort # too many false positives - - golint # deprecated - varnamelen - tagliatelle - errname - ireturn - exhaustruct - nonamedreturns - - nosnakecase - - structcheck - - varcheck - - deadcode - testableexamples - dupword - depguard - tagalign + - execinquery + - mnd + - testifylint issues: exclude-use-default: false exclude-rules: - linters: - gomnd + - mnd - goconst - goerr113 - noctx @@ -71,4 +65,7 @@ issues: - errcheck # Error checking omitted for brevity. - gosec path: "example_" + - linters: + - revive + text: "unused-parameter: parameter" diff --git a/Makefile b/Makefile index caf1cf0..c7a1f46 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -#GOLANGCI_LINT_VERSION := "v1.56.2" # Optional configuration to pinpoint golangci-lint version. +#GOLANGCI_LINT_VERSION := "v1.61.0" # Optional configuration to pinpoint golangci-lint version. # The head of Makefile determines location of dev-go to include standard targets. GO ?= go diff --git a/go.mod b/go.mod index 5df2d84..192208a 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/bool64/progress go 1.21 require ( - github.com/DataDog/zstd v1.5.5 - github.com/bool64/dev v0.2.34 - github.com/klauspost/compress v1.17.8 + github.com/DataDog/zstd v1.5.6 + github.com/bool64/dev v0.2.36 + github.com/klauspost/compress v1.17.10 github.com/klauspost/pgzip v1.2.6 ) diff --git a/go.sum b/go.sum index e2b52ff..1ef0c07 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,8 @@ -github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= -github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/bool64/dev v0.2.33 h1:ETAcSa8H9w4talcCdSQCCnLX7PMHmuxdLcDl6TpSDj4= -github.com/bool64/dev v0.2.33/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= -github.com/bool64/dev v0.2.34 h1:P9n315P8LdpxusnYQ0X7MP1CZXwBK5ae5RZrd+GdSZE= -github.com/bool64/dev v0.2.34/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= -github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= +github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/bool64/dev v0.2.36 h1:yU3bbOTujoxhWnt8ig8t94PVmZXIkCaRj9C57OtqJBY= +github.com/bool64/dev v0.2.36/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= +github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= +github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= diff --git a/progress.go b/progress.go index b5d5649..cf1c25a 100644 --- a/progress.go +++ b/progress.go @@ -14,6 +14,7 @@ type Status struct { Task string `json:"task"` DonePercent float64 `json:"done_percent"` LinesCompleted int64 `json:"lines_completed"` + BytesCompleted int64 `json:"bytes_completed"` SpeedMBPS float64 `json:"speed_mbps"` SpeedLPS float64 `json:"speed_lps"` Elapsed time.Duration `json:"-"` @@ -27,13 +28,20 @@ type Progress struct { Print func(status Status) ShowHeapStats bool ShowLinesStats bool - done chan bool - task Task - lines func() int64 - current func() int64 - tot func() int64 - prnt func(s Status) - start time.Time + + // IncrementalSpeed shows speed and remaining estimate based on performance between two status updates. + IncrementalSpeed bool + + done chan bool + task Task + lines func() int64 + current func() int64 + tot func() int64 + prnt func(s Status) + start time.Time + + prevStatus Status + continuedLines int64 continuedBytes int64 metrics []Metric @@ -191,16 +199,34 @@ func (p *Progress) Reset() { p.metrics = nil } -func (p *Progress) printStatus(last bool) { - s := Status{} - s.Task = p.task.Task - s.LinesCompleted = p.Lines() - s.Metrics = p.metrics +func (p *Progress) speedStatus(s *Status) { + if p.IncrementalSpeed { + lc := s.LinesCompleted - p.prevStatus.LinesCompleted + bc := s.BytesCompleted - p.prevStatus.BytesCompleted + dc := s.DonePercent - p.prevStatus.DonePercent + ela := s.Elapsed - p.prevStatus.Elapsed - b := float64(p.Bytes()) - s.DonePercent = 100 * b / float64(p.tot()) - s.Elapsed = time.Since(p.start) - s.SpeedMBPS = (b / s.Elapsed.Seconds()) / (1024 * 1024) + if lc > 0 { + s.SpeedLPS = float64(lc) / ela.Seconds() + } + + if bc > 0 { + s.SpeedMBPS = (float64(bc) / ela.Seconds()) / (1024 * 1024) + } + + if s.DonePercent > 0 { + s.Remaining = time.Duration((100.0 - s.DonePercent) * float64(ela) / dc) + s.Remaining = s.Remaining.Truncate(time.Second) + } else { + s.Remaining = 0 + } + + p.prevStatus = *s + + return + } + + s.SpeedMBPS = (float64(s.BytesCompleted) / s.Elapsed.Seconds()) / (1024 * 1024) s.SpeedLPS = float64(s.LinesCompleted) / s.Elapsed.Seconds() if s.DonePercent > 0 { @@ -209,6 +235,18 @@ func (p *Progress) printStatus(last bool) { } else { s.Remaining = 0 } +} + +func (p *Progress) printStatus(last bool) { + s := Status{} + s.Task = p.task.Task + s.LinesCompleted = p.Lines() + s.BytesCompleted = p.Bytes() + s.Metrics = p.metrics + s.Elapsed = time.Since(p.start) + s.DonePercent = 100 * float64(s.BytesCompleted) / float64(p.tot()) + + p.speedStatus(&s) if s.Remaining > 100*time.Millisecond || s.Remaining == 0 || last { p.prnt(s)