如何检查链接到我的 Go 代码的包的大小

跟进如何检查 Go 项目的大小?

结论是:

为了真正了解导入某些包有多少额外的重量,还必须查看 pkg 的所有子依赖项。

这是完全可以理解的。我的问题是,

无论如何,我是否可以知道每个组件在我编译的二进制文件、Go 运行时、依赖项和子依赖项包以及我自己的代码中占用了多少空间。

我依稀记得以前读过类似的东西(也许当 go 增强了它的链接器时)。
如果以前从未有过这样的讨论,那么 go 甚至 c 链接器有什么方法可以查看我编译的二进制文件,并揭示一些我可以进一步解析的内容吗?


交互式爱情
浏览 156回答 2
2回答

守着一只汪

二进制文件将包含调试符号,我们可以使用它来计算每个包占用多少空间。我编写了一个基本程序来执行此操作,因为我不知道有任何工具可以执行此操作:package mainimport (    "debug/elf"    "fmt"    "os"    "runtime"    "sort"    "strings"    "github.com/go-delve/delve/pkg/proc")func main() {    // Use delve to decode the DWARF section    binInfo := proc.NewBinaryInfo(runtime.GOOS, runtime.GOARCH)    err := binInfo.AddImage(os.Args[1], 0)    if err != nil {        panic(err)    }    // Make a list of unique packages    pkgs := make([]string, 0, len(binInfo.PackageMap))    for _, fullPkgs := range binInfo.PackageMap {        for _, fullPkg := range fullPkgs {            exists := false            for _, pkg := range pkgs {                if fullPkg == pkg {                    exists = true                    break                }            }            if !exists {                pkgs = append(pkgs, fullPkg)            }        }    }    // Sort them for a nice output    sort.Strings(pkgs)    // Parse the ELF file ourselfs    elfFile, err := elf.Open(os.Args[1])    if err != nil {        panic(err)    }    // Get the symbol table    symbols, err := elfFile.Symbols()    if err != nil {        panic(err)    }    usage := make(map[string]map[string]int)    for _, sym := range symbols {        if sym.Section == elf.SHN_UNDEF || sym.Section >= elf.SectionIndex(len(elfFile.Sections)) {            continue        }        sectionName := elfFile.Sections[sym.Section].Name        symPkg := ""        for _, pkg := range pkgs {            if strings.HasPrefix(sym.Name, pkg) {                symPkg = pkg                break            }        }        // Symbol doesn't belong to a known package        if symPkg == "" {            continue        }        pkgStats := usage[symPkg]        if pkgStats == nil {            pkgStats = make(map[string]int)        }        pkgStats[sectionName] += int(sym.Size)        usage[symPkg] = pkgStats    }    for _, pkg := range pkgs {        sections, exists := usage[pkg]        if !exists {            continue        }        fmt.Printf("%s:\n", pkg)        for section, size := range sections {            fmt.Printf("%15s: %8d bytes\n", section, size)        }        fmt.Println()    }}现在实际使用的空间被划分为多个部分(.text 用于代码,.bss 用于零初始化数据,.data 用于全局变量等)。此示例列出了每个部分的大小,但如果您愿意,可以修改代码以获取总数。这是它从自己的二进制文件生成的输出:bufio:          .text:    12733 bytes     .noptrdata:       64 bytes           .bss:      176 bytes        .rodata:       72 bytesbytes:           .bss:       48 bytes        .rodata:       64 bytes          .text:    12617 bytes     .noptrdata:      320 bytescompress/flate:          .text:    20385 bytes     .noptrdata:      248 bytes           .bss:     2112 bytes      .noptrbss:       12 bytes        .rodata:       48 bytescompress/zlib:          .text:     4138 bytes     .noptrdata:       96 bytes           .bss:       48 bytescontainer/list:          .text:     4016 bytescontext:          .text:      387 bytes     .noptrdata:       72 bytes           .bss:       40 bytescrypto:          .text:    20982 bytes     .noptrdata:      416 bytes           .bss:       96 bytes        .rodata:       58 bytes      .noptrbss:        3 bytesdebug/dwarf:        .rodata:     1088 bytes          .text:   113878 bytes     .noptrdata:      247 bytes           .bss:       64 bytesdebug/elf:        .rodata:      168 bytes          .text:    36557 bytes     .noptrdata:      112 bytes          .data:     5160 bytes           .bss:       16 bytesdebug/macho:          .text:    22980 bytes     .noptrdata:       96 bytes          .data:      456 bytes        .rodata:       80 bytesdebug/pe:          .text:    26004 bytes     .noptrdata:       96 bytes        .rodata:      288 bytesencoding/base64:           .bss:       32 bytes        .rodata:       48 bytes          .text:      846 bytes     .noptrdata:       56 bytesencoding/binary:          .text:    27108 bytes     .noptrdata:       72 bytes           .bss:       56 bytes        .rodata:      136 bytesencoding/hex:           .bss:       16 bytes          .text:      288 bytes     .noptrdata:       64 bytesencoding/json:        .rodata:      108 bytes          .text:     2930 bytes     .noptrdata:      128 bytes           .bss:       80 byteserrors:        .rodata:       48 bytes          .text:      744 bytes     .noptrdata:       40 bytes           .bss:       16 bytesfmt:          .text:    72010 bytes     .noptrdata:      136 bytes          .data:      104 bytes           .bss:       32 bytes        .rodata:      720 bytesgithub.com/cilium/ebpf:          .text:   170860 bytes     .noptrdata:     1405 bytes           .bss:      608 bytes        .rodata:     3971 bytes          .data:       16 bytes      .noptrbss:        8 bytesgithub.com/go-delve/delve/pkg/dwarf/frame:          .text:    18304 bytes     .noptrdata:       80 bytes           .bss:        8 bytes        .rodata:      211 bytesgithub.com/go-delve/delve/pkg/dwarf/godwarf:          .text:    40431 bytes     .noptrdata:      144 bytes        .rodata:      352 bytesgithub.com/go-delve/delve/pkg/dwarf/line:           .bss:       48 bytes        .rodata:      160 bytes          .text:    24069 bytes     .noptrdata:       96 bytesgithub.com/go-delve/delve/pkg/dwarf/loclist:     .noptrdata:       64 bytes        .rodata:       64 bytes          .text:     4538 bytesgithub.com/go-delve/delve/pkg/dwarf/op:          .text:    31142 bytes     .noptrdata:       80 bytes           .bss:       72 bytes        .rodata:     5313 bytesgithub.com/go-delve/delve/pkg/dwarf/reader:     .noptrdata:       72 bytes           .bss:       16 bytes        .rodata:       24 bytes          .text:     8037 bytesgithub.com/go-delve/delve/pkg/dwarf/regnum:           .bss:       40 bytes        .rodata:     2760 bytes          .text:     3943 bytes     .noptrdata:       48 bytesgithub.com/go-delve/delve/pkg/dwarf/util:          .text:     4028 bytes     .noptrdata:       64 bytes        .rodata:       96 bytesgithub.com/go-delve/delve/pkg/elfwriter:          .text:     3394 bytes     .noptrdata:       48 bytes        .rodata:       48 bytesgithub.com/go-delve/delve/pkg/goversion:     .noptrdata:      104 bytes           .bss:       64 bytes        .rodata:      160 bytes          .text:     4415 bytesgithub.com/go-delve/delve/pkg/logflags:           .bss:       32 bytes        .rodata:       40 bytes          .text:     2610 bytes     .noptrdata:      136 bytes      .noptrbss:        3 bytesgithub.com/go-delve/delve/pkg/proc:          .text:   432477 bytes     .noptrdata:      718 bytes          .data:     1448 bytes           .bss:      592 bytes        .rodata:    10106 bytesgithub.com/go-delve/delve/pkg/version:          .text:     1509 bytes     .noptrdata:       72 bytes          .data:      112 bytes        .rodata:       40 bytesgithub.com/hashicorp/golang-lru/simplelru:          .text:     3911 bytes     .noptrdata:       32 bytes        .rodata:      160 bytesgithub.com/sirupsen/logrus:      .noptrbss:       20 bytes        .rodata:      696 bytes          .text:    40175 bytes     .noptrdata:      204 bytes          .data:       64 bytes           .bss:       56 bytesgo/ast:          .text:    24407 bytes     .noptrdata:      104 bytes          .data:      112 bytes        .rodata:      120 bytesgo/constant:           .bss:        8 bytes        .rodata:      824 bytes          .text:    33910 bytes     .noptrdata:       88 bytesgo/parser:        .rodata:     1808 bytes          .text:    78751 bytes     .noptrdata:      136 bytes           .bss:       32 bytesgo/printer:          .text:    77202 bytes     .noptrdata:      113 bytes          .data:       24 bytes        .rodata:     1504 bytesgo/scanner:        .rodata:      240 bytes          .text:    18594 bytes     .noptrdata:       93 bytes          .data:       24 bytesgo/token:     .noptrdata:       72 bytes          .data:     1376 bytes           .bss:        8 bytes        .rodata:      192 bytes          .text:     7154 bytesgolang.org/x/arch/arm64/arm64asm:        .rodata:      856 bytes          .text:   116428 bytes     .noptrdata:       80 bytes           .bss:       80 bytes          .data:    46128 bytesgolang.org/x/arch/x86/x86asm:     .noptrdata:    29125 bytes           .bss:      112 bytes          .data:    20928 bytes        .rodata:     1252 bytes          .text:    76721 bytesgolang.org/x/sys/unix:          .text:     1800 bytes     .noptrdata:      128 bytes        .rodata:       70 bytes          .data:       80 byteshash/adler32:          .text:     1013 bytes     .noptrdata:       40 bytesinternal/bytealg:        .rodata:       56 bytes      .noptrbss:        8 bytes          .text:     1462 bytes     .noptrdata:       32 bytesinternal/cpu:        .rodata:      500 bytes      .noptrbss:      416 bytes     .noptrdata:        8 bytes           .bss:       24 bytes          .text:     3017 bytesinternal/fmtsort:          .text:     7443 bytes     .noptrdata:       40 bytes        .rodata:       40 bytesinternal/oserror:          .text:      500 bytes     .noptrdata:       40 bytes           .bss:       80 bytesinternal/poll:          .text:    31565 bytes        .rodata:      192 bytes     .noptrdata:      112 bytes          .data:       96 bytes           .bss:       64 bytes      .noptrbss:       12 bytesinternal/reflectlite:          .text:    13761 bytes     .noptrdata:       32 bytes          .data:      456 bytes           .bss:       24 bytes        .rodata:      496 bytesinternal/syscall/unix:        .rodata:       72 bytes          .text:      708 bytes     .noptrdata:       40 bytes      .noptrbss:        4 bytesinternal/testlog:          .text:      827 bytes     .noptrdata:       32 bytes      .noptrbss:       12 bytes           .bss:       16 bytes        .rodata:       72 bytesio:     .noptrdata:      240 bytes           .bss:      272 bytes          .data:       56 bytes      .noptrbss:        0 bytes        .rodata:      128 bytes          .text:    10824 byteslog:          .text:      188 bytes     .noptrdata:       80 bytes           .bss:        8 bytesmain:          .text:     3002 bytes     .noptrdata:       80 bytes        .rodata:      104 bytesmath:          .data:      136 bytes           .bss:     2672 bytes          .text:   184385 bytes     .noptrdata:    10211 bytes        .rodata:     2076 bytes      .noptrbss:        2 bytesnet:          .text:    24417 bytes     .noptrdata:      236 bytes          .data:      240 bytes           .bss:      584 bytes      .noptrbss:       16 bytes        .rodata:       48 bytesos:           .bss:      264 bytes          .data:       32 bytes        .rodata:      352 bytes          .text:    46276 bytes     .noptrdata:      296 bytes      .noptrbss:        1 bytespath:          .text:     9378 bytes     .noptrdata:      136 bytes           .bss:       48 bytes        .rodata:       48 bytesreflect:      .noptrbss:        1 bytes          .text:    97417 bytes     .noptrdata:       72 bytes        .rodata:     1728 bytes          .data:      456 bytes           .bss:      160 bytesregexp:        .rodata:      968 bytes          .text:   126451 bytes     .noptrdata:      558 bytes           .bss:      296 bytes      .noptrbss:       16 bytes          .data:      816 bytesruntime:      .noptrbss:    20487 bytes          .data:     8520 bytes           .bss:   184836 bytes          .tbss:        8 bytes      .typelink:     9020 bytes     .gopclntab:        0 bytes          .text:   408713 bytes     .noptrdata:     4347 bytes        .rodata:    23102 bytes      .itablink:     2952 bytessort:          .text:    13055 bytes     .noptrdata:       32 bytes          .data:       16 bytes        .rodata:       24 bytesstrconv:          .text:    45928 bytes     .noptrdata:    17015 bytes          .data:     1680 bytes           .bss:       32 bytes        .rodata:      144 bytesstrings:          .text:    21070 bytes     .noptrdata:      320 bytes        .rodata:      168 bytessync:        .rodata:      476 bytes     .noptrdata:       56 bytes           .bss:       56 bytes      .noptrbss:        8 bytes          .text:    14288 bytessyscall:     .noptrdata:      127 bytes        .rodata:      978 bytes      .noptrbss:       76 bytes           .bss:      264 bytes          .data:     2720 bytes          .text:    33728 bytestext/tabwriter:          .data:       96 bytes        .rodata:       88 bytes          .text:     8002 bytes     .noptrdata:       46 bytestext/template:          .text:   166284 bytes     .noptrdata:      316 bytes      .noptrbss:        8 bytes           .bss:      176 bytes          .data:      376 bytes        .rodata:     3152 bytestime:          .text:    83290 bytes     .noptrdata:      164 bytes          .data:      912 bytes           .bss:      208 bytes      .noptrbss:       20 bytes        .rodata:      832 bytesunicode:     .noptrdata:    50398 bytes          .data:    15248 bytes           .bss:       40 bytes      .noptrbss:        0 bytes          .text:    27198 bytes注意这个程序并不完美,它只适用于 Linux/Mac,因为它依赖于 ELF。我相信您可以对 Windows PE 文件执行类似的操作,但这会花费我很多时间。此外,这个程序忽略了 go 运行时的某些部分,但我猜这对你来说不是最重要的。

慕标琳琳

您可以运行nm以获取二进制文件中所有对象的大小。示例:nm -S /usr/local/go/bin/gofmt。第二列是大小。0000000000468700 000000000000011c T unicode/utf8.DecodeLastRuneInString0000000000468240 00000000000001a6 T unicode/utf8.DecodeRune0000000000468400 00000000000001a6 T unicode/utf8.DecodeRuneInString0000000000468820 0000000000000157 T unicode/utf8.EncodeRune
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go