Search code examples
godependencies

Finding largest imported package in Go binary


My project has a huge binary (23MB, usually only 11MB-ish), when I check the binary using go tool, but it shows per package name instead of per directly imported package on the project:

23 075 950 (23 MB)
go tool nm -sort size -size ApiServerQ | head -n 20

  fb12c0    4874612 r runtime.pclntab
  a741e0     669338 T github.com/aws/aws-sdk-go/aws/endpoints.init
  87a200     305452 T github.com/xdg/stringprep.init
 14d0c80      75600 D runtime.mheap_
 14c0ba0      65744 D runtime.trace
  fa0b60      38267 r runtime.findfunctab
 149c6a0      30720 D crypto/ed25519/internal/edwards25519.base
  62cd20      20993 T vendor/golang.org/x/crypto/chacha20poly1305.chacha20Poly1305Seal
  faae40      20892 r runtime.typelink
  4a4680      20413 T unicode.init
 1497be0      19108 D vendor/golang.org/x/text/unicode/norm.decomps
 1493120      19105 D golang.org/x/text/unicode/norm.decomps
  628480      18589 T vendor/golang.org/x/crypto/chacha20poly1305.chacha20Poly1305Open
 148f1a0      16256 D vendor/golang.org/x/net/idna.idnaValues
  5c9080      16152 T crypto/sha512.blockAMD64
 14bcce0      16064 D runtime.semtable
 14e6c80      15384 D github.com/klauspost/compress/zstd.fsePredef
 148b5a0      15360 D vendor/golang.org/x/text/unicode/bidi.bidiValues
  485520      15154 T time.parse
  859d20      14875 T go.mongodb.org/mongo-driver/x/mongo/driver/operation.(*IsMaster).Result

Compared to my old one project (ScyllaDB):

16 699 093 (16 MB)
go tool nm -sort size -size UserMicro | head -n 20 
  c94140    3345240 r runtime.pclntab
  88fee0     625345 T github.com/aws/aws-sdk-go/aws/endpoints.init
 1026020      65744 D runtime.trace
  543070      32787 T github.com/yuin/gopher-lua/parse.yyParse
  715c60      30757 T github.com/aerospike/aerospike-client-go.tryConcreteValue
  ffeb60      30720 D crypto/ed25519/internal/edwards25519.base
  c87080      27476 r runtime.findfunctab
  64fae0      20993 T vendor/golang.org/x/crypto/chacha20poly1305.chacha20Poly1305Seal
  499750      20065 T unicode.init
  70d400      19890 T github.com/aerospike/aerospike-client-go.setValue
  ffa0a0      19105 D vendor/golang.org/x/text/unicode/norm.decomps
  64b240      18589 T vendor/golang.org/x/crypto/chacha20poly1305.chacha20Poly1305Open
  c8e8e0      17060 r runtime.typelink
  ff6120      16256 D vendor/golang.org/x/net/idna.idnaValues
  5c09d0      16152 T crypto/sha512.blockAMD64
 1022160      16064 D runtime.semtable
  ff26a0      14976 D vendor/golang.org/x/text/unicode/bidi.bidiValues
  59e0c0      14842 T github.com/yuin/gopher-lua.init
  5eac20      14482 T crypto/sha256.block
  5c7bc0      14174 T encoding/asn1.parseField

And other older one (MemSQL+GORM):

15 438 537 (15 MB)
go tool nm -sort size -size MonolithI | head -n 20
  b24500    3556591 r runtime.pclntab
  ee3960      65744 D runtime.trace
  ebbf60      30720 D crypto/ed25519/internal/edwards25519.base
  b182e0      26236 r runtime.findfunctab
  652aa0      20993 T vendor/golang.org/x/crypto/chacha20poly1305.chacha20Poly1305Seal
  46f7b0      20065 T unicode.init
  eb74a0      19105 D vendor/golang.org/x/text/unicode/norm.decomps
  64e200      18589 T vendor/golang.org/x/crypto/chacha20poly1305.chacha20Poly1305Open
  b1f6a0      16520 r runtime.typelink
  eb3520      16256 D vendor/golang.org/x/net/idna.idnaValues
  5f8a00      16152 T crypto/sha512.blockAMD64
  edfaa0      16064 D runtime.semtable
  eafaa0      14976 D vendor/golang.org/x/text/unicode/bidi.bidiValues
  5a3300      14482 T crypto/sha256.block
  5ffc90      14174 T encoding/asn1.parseField
  4ba780      13913 T time.parse
  8857e0      13733 T net/http.init
  7dd940      13729 T github.com/go-sql-driver/mysql.parseDSNParams
  7b21a0      12577 T github.com/kokizzu/gorm.(*Scope).buildCondition
  768030      12202 T database/sql.convertAssignRows

and the other one (PostgreSQL):

12 007 258 (12 MB)
go tool nm -sort size -size MonolithYOD | head -n 20
  9914a0    2696675 r runtime.pclntab
  c6d0c0      65744 D runtime.trace
  4667d0      22868 T unicode.init.ializers
  604f00      20993 T internal/x/crypto/chacha20poly1305.chacha20Poly1305Seal
  987a40      19967 r runtime.findfunctab
  c4c340      19105 D internal/x/text/unicode/norm.decomps
  74bb00      19020 T github.com/tdewolff/minify/css.init.ializers
  600660      18589 T internal/x/crypto/chacha20poly1305.chacha20Poly1305Open
  c483c0      16256 D internal/x/net/idna.idnaValues
  7a4de0      16186 T github.com/nfnt/resize.Resize
  5bc930      16152 T crypto/sha512.blockAMD64
  c69200      16064 D runtime.semtable
  7a8d20      14984 T github.com/nfnt/resize.resizeNearest
  5c4000      14964 T encoding/asn1.parseField
  c44ac0      14592 D internal/x/text/unicode/bidi.bidiValues
  55abc0      14482 T crypto/sha256.block
  6f7e10      13890 T net/http.init.ializers
  7bbb40      13555 T image/png.(*decoder).readImagePass
  98d680      12544 r runtime.typelink
  4d9bb0      12353 T encoding/json.(*decodeState).literalStore

and the other one (PostgreSQL):

14 127 727 (14 MB)
go tool nm -sort size -size MonolithL | head -n 20        
  a94080    2899496 r runtime.pclntab
  e095e0      75600 D runtime.mheap_
  df9500      65744 D runtime.trace
  73a9c0      35788 T github.com/tdewolff/minify/css.(*cssMinifier).minifyProperty
  d8e380      30720 D crypto/ed25519/internal/edwards25519.base
  845d10      26470 T github.com/golang/freetype/truetype.(*hinter).run
  744510      25126 T github.com/tdewolff/minify/css.init
  a895c0      23278 r runtime.findfunctab
  60a110      20993 T vendor/golang.org/x/crypto/chacha20poly1305.chacha20Poly1305Seal
  472ff0      20413 T unicode.init
  d898c0      19108 D vendor/golang.org/x/text/unicode/norm.decomps
  605870      18589 T vendor/golang.org/x/crypto/chacha20poly1305.chacha20Poly1305Open
  d85940      16256 D vendor/golang.org/x/net/idna.idnaValues
  5ba1e0      16152 T crypto/sha512.blockAMD64
  df5640      16064 D runtime.semtable
  7cb220      16012 T github.com/nfnt/resize.Resize
  d81d40      15360 D vendor/golang.org/x/text/unicode/bidi.bidiValues
  4879e0      15154 T time.parse
  7cf0b0      14806 T github.com/nfnt/resize.resizeNearest
  56b880      14482 T crypto/sha256.block

The question is, which package that causes this bloat? because it took time to upload the binary to the server if without external CI/CD (even after upx and ldflags-s-w), or which one of project's direct import that indirectly import that huge package?

Already tried gofat but it didn't show correct package name (it shows obfuscated package name), also tried goweight but it shows exit status 1.


Solution

  • Nevermind, goweight solves the problem, apparently I was running goweight in wrong directory before. I also found out that redis.v7 and aws-sdk-go that imported by overseer/fetcher (checked by depth) is the culprit.

    goweight . | head -n 20
      8.7 MB github.com/go-redis/redis/v7
      7.3 MB github.com/aws/aws-sdk-go/service/s3
      3.9 MB net/http
      3.8 MB runtime
      3.3 MB github.com/gocql/gocql
      2.8 MB github.com/aws/aws-sdk-go/aws/endpoints
      2.5 MB github.com/valyala/fasthttp
      1.9 MB go.mongodb.org/mongo-driver/mongo
      1.8 MB net
      1.8 MB crypto/tls
      1.5 MB go.mongodb.org/mongo-driver/x/mongo/driver/operation
      1.5 MB golang.org/x/sys/unix
      1.4 MB reflect
      1.2 MB github.com/xdg/stringprep
      1.2 MB go.mongodb.org/mongo-driver/bson/bsoncodec
      1.2 MB go.mongodb.org/mongo-driver/x/mongo/driver
      1.1 MB go.mongodb.org/mongo-driver/bson/bsonrw
      1.0 MB github.com/klauspost/compress/zstd
      998 kB math/big
      916 kB go.mongodb.org/mongo-driver/x/mongo/driver/topology
    
    depth . | less
      │ ├ github.com/jpillora/overseer/fetcher
      │ │ ├ compress/gzip
      │ │ ├ encoding/json
            ...
      │ │ ├ net/http
      │ │ ├ os
      │ │ ├ github.com/aws/aws-sdk-go/aws
    
    

    Update After downgrading to redis.v5 and updating to latest overseer that removes aws-sdk, also removing gocqlx it reduces to 18MB (13MB if using ldflags-s-w, 4MB if using upx)

    goweight . | head -n 20
      3.9 MB net/http
      3.8 MB runtime
      3.0 MB gopkg.in/redis.v5
      2.5 MB github.com/valyala/fasthttp
      1.9 MB go.mongodb.org/mongo-driver/mongo
      1.8 MB net
      1.8 MB crypto/tls
      1.5 MB go.mongodb.org/mongo-driver/x/mongo/driver/operation
      1.5 MB golang.org/x/sys/unix
      1.4 MB reflect
      1.2 MB github.com/xdg/stringprep
      1.2 MB go.mongodb.org/mongo-driver/bson/bsoncodec
      1.2 MB go.mongodb.org/mongo-driver/x/mongo/driver
      1.1 MB go.mongodb.org/mongo-driver/bson/bsonrw
      1.0 MB github.com/klauspost/compress/zstd
      998 kB math/big
      916 kB go.mongodb.org/mongo-driver/x/mongo/driver/topology
      847 kB syscall
      828 kB go.mongodb.org/mongo-driver/x/bsonx
      802 kB gopkg.in/mgo.v2/internal/json