Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/crypto/bcrypt: memory usage #26122

Closed
henriquechehad opened this issue Jun 29, 2018 · 6 comments
Closed

x/crypto/bcrypt: memory usage #26122

henriquechehad opened this issue Jun 29, 2018 · 6 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Milestone

Comments

@henriquechehad
Copy link

henriquechehad commented Jun 29, 2018

What version of Go are you using (go version)?

go version go1.9.2 darwin/amd64

Does this issue reproduce with the latest release?

Latest x/crypto/bcrypt

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/henriquechehad/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/qd/mjm4kwn53k3b2zmzl_5pkznh0000gn/T/go-build787818303=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

Description

During the project usage, I noticed that the memory allocation is always increasing during requests and not decreasing after stopping the requests, there's a memory leak. I used pprof to try to find it and saw with the heap that the bcrypt was with almost all the memory usage during the usage. As I don't have experience with bcrypt implementation, I can not ensure that it's the issue. But it sounds like a thing to check. It's by far the project part that is more allocating memory.

(pprof) top --alloc_space
Ignore expression matched no samples
Showing nodes accounting for 160.98s, 98.06% of 164.16s total
Dropped 488 nodes (cum <= 0.82s)
Showing top 10 nodes out of 65
      flat  flat%   sum%        cum   cum%
   137.53s 83.78% 83.78%    137.53s 83.78%  github.com/----/----/vendor/golang.org/x/crypto/blowfish.encryptBlock /Users/henriquechehad/go/src/github.com/---/----/vendor/golang.org/x/crypto/blowfish/block.go
     7.42s  4.52% 88.30%      7.42s  4.52%  runtime.duffcopy /usr/local/go/src/runtime/duff_amd64.s
     5.45s  3.32% 91.62%    142.93s 87.07%  github.com/----/----/vendor/golang.org/x/crypto/blowfish.ExpandKey /Users/henriquechehad/go/src/github.com/----/----/vendor/golang.org/x/crypto/blowfish/block.go
     3.16s  1.92% 93.54%      3.16s  1.92%  runtime.mach_semaphore_signal /usr/local/go/src/runtime/sys_darwin_amd64.s
     2.60s  1.58% 95.13%      2.60s  1.58%  runtime.usleep /usr/local/go/src/runtime/sys_darwin_amd64.s
     2.39s  1.46% 96.58%      2.39s  1.46%  runtime.memclrNoHeapPointers /usr/local/go/src/runtime/memclr_amd64.s
     2.19s  1.33% 97.92%      2.35s  1.43%  syscall.Syscall /usr/local/go/src/syscall/asm_darwin_amd64.s
     0.17s   0.1% 98.02%    145.59s 88.69%  github.com/----/----/vendor/golang.org/x/crypto/bcrypt.CompareHashAndPassword /Users/henriquechehad/go/src/github.com/----/----/vendor/golang.org/x/crypto/bcrypt/bcrypt.go

Seems it's specifically in this function: https://github.com/golang/crypto/blob/master/blowfish/block.go#L115

The code that calls it:

err = bcrypt.CompareHashAndPassword([]byte(hashPassword), []byte(password))
@gopherbot gopherbot added this to the Unreleased milestone Jun 29, 2018
@FiloSottile FiloSottile changed the title x/crypto: memory usage x/crypto/bcrypt: memory usage Jun 29, 2018
@FiloSottile FiloSottile added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Jun 29, 2018
@FiloSottile
Copy link
Contributor

--alloc_space tells you about what functions allocated the most over the lifetime of your program, even if that memory got garbage collected. It's normal to see bcrypt show up there.

To debug a leak you want to use --inuse_space on a profile captured during execution.

@FiloSottile FiloSottile added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Jun 29, 2018
@henriquechehad
Copy link
Author

Hi @FiloSottile

using --inuse_space:

(pprof) top --inuse_space
Ignore expression matched no samples
Showing nodes accounting for 335.58s, 98.17% of 341.83s total
Dropped 624 nodes (cum <= 1.71s)
Showing top 10 nodes out of 64
      flat  flat%   sum%        cum   cum%
   290.58s 85.01% 85.01%    290.58s 85.01%  github.com/----/----/vendor/golang.org/x/crypto/blowfish.encryptBlock /Users/henriquechehad/go/src/github.com/----/----/vendor/golang.org/x/crypto/blowfish/block.go
    13.58s  3.97% 88.98%     13.58s  3.97%  runtime.duffcopy /usr/local/go/src/runtime/duff_amd64.s
    11.85s  3.47% 92.45%    302.34s 88.45%  github.com/----/----/vendor/golang.org/x/crypto/blowfish.ExpandKey /Users/henriquechehad/go/src/github.com/----/----/vendor/golang.org/x/crypto/blowfish/block.go
     5.71s  1.67% 94.12%      5.71s  1.67%  runtime.mach_semaphore_signal /usr/local/go/src/runtime/sys_darwin_amd64.s
     5.03s  1.47% 95.59%      5.03s  1.47%  runtime.usleep /usr/local/go/src/runtime/sys_darwin_amd64.s
     4.39s  1.28% 96.87%      4.77s  1.40%  syscall.Syscall /usr/local/go/src/syscall/asm_darwin_amd64.s
     4.14s  1.21% 98.08%      4.14s  1.21%  runtime.memclrNoHeapPointers /usr/local/go/src/runtime/memclr_amd64.s
     0.21s 0.061% 98.15%    306.85s 89.77%  github.com/----/----/vendor/golang.org/x/crypto/bcrypt.CompareHashAndPassword /Users/henriquechehad/go/src/github.com/----/----/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
     0.06s 0.018% 98.16%      4.68s  1.37%  runtime.mallocgc /usr/local/go/src/runtime/malloc.go
     0.03s 0.0088% 98.17%      2.38s   0.7%  runtime.findrunnable /usr/local/go/src/runtime/proc.go

@meirf
Copy link
Contributor

meirf commented Jul 4, 2018

To make it easier for us to reproduce your results, can you try writing up standalone code that we can run? Obviously, we don't want your code to include actual passwords from your production environment. (I wasn't able to reproduce your results, but maybe your usage pattern is affecting memory usage.)

If you write it in the form of a benchmark, you can run go test -bench=. -memprofile mem.out to create a memory profile and then run go tool pprof mem.out

@henriquechehad
Copy link
Author

@meirf I tried two ways to reproduce, one with the code in a main(), compiling and using pkg/profile. The other with benchmark. The first way I could reproduce but not with the second.

  1. https://gist.github.com/henriquechehad/3692a2818670881252608fd788b68243
  2. https://gist.github.com/henriquechehad/c66191032423c2927654c1bd760d2caa

@meirf
Copy link
Contributor

meirf commented Jul 6, 2018

https://gist.github.com/henriquechehad/3692a2818670881252608fd788b68243
https://gist.github.com/henriquechehad/c66191032423c2927654c1bd760d2caa

I don't see proof of any problem from these gists. The first link shows NewSaltedCipher is allocating some memory and if you run list NewSaltedCipher you'll see it attributed to var result Cipher which is expected since Cipher takes up about 4KB. If you put runtime.GC() at the end of main, you'll see that the memory drops way down which makes me think that there is no leak or that the GC isn't running when you need it to. Regarding the second link, I recommend this to get better acquainted with go benchmarks.

Also, now that I look more closely at your pprof output above I notice the unit is time instead of space so I think you were running pprof on a cpu profile instead of a memory profile. Time can impact space - if there's not enough time, there might not be enough time to gc, but I don't think that's what you intended in your output.

@henriquechehad
Copy link
Author

Thanks for the clarification @meirf and @FiloSottile. It's not the issue then. Appreciate your help.

@golang golang locked and limited conversation to collaborators Jul 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

4 participants