为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
交互式爱情 2022-10-24 17:04:05
跟进如何检查 Go 项目的大小?结论是:为了真正了解导入某些包有多少额外的重量,还必须查看 pkg 的所有子依赖项。这是完全可以理解的。我的问题是,无论如何,我是否可以知道每个组件在我编译的二进制文件、Go 运行时、依赖项和子依赖项包以及我自己的代码中占用了多少空间。我依稀记得以前读过类似的东西(也许当 go 增强了它的链接器时)。如果以前从未有过这样的讨论,那么 go 甚至 c 链接器有什么方法可以查看我编译的二进制文件,并揭示一些我可以进一步解析的内容吗?
查看完整描述

2 回答

?
守着一只汪

TA贡献1872条经验 获得超3个赞

二进制文件将包含调试符号,我们可以使用它来计算每个包占用多少空间。


我编写了一个基本程序来执行此操作,因为我不知道有任何工具可以执行此操作:


package main


import (

    "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 bytes


bytes:

           .bss:       48 bytes

        .rodata:       64 bytes

          .text:    12617 bytes

     .noptrdata:      320 bytes


compress/flate:

          .text:    20385 bytes

     .noptrdata:      248 bytes

           .bss:     2112 bytes

      .noptrbss:       12 bytes

        .rodata:       48 bytes


compress/zlib:

          .text:     4138 bytes

     .noptrdata:       96 bytes

           .bss:       48 bytes


container/list:

          .text:     4016 bytes


context:

          .text:      387 bytes

     .noptrdata:       72 bytes

           .bss:       40 bytes


crypto:

          .text:    20982 bytes

     .noptrdata:      416 bytes

           .bss:       96 bytes

        .rodata:       58 bytes

      .noptrbss:        3 bytes


debug/dwarf:

        .rodata:     1088 bytes

          .text:   113878 bytes

     .noptrdata:      247 bytes

           .bss:       64 bytes


debug/elf:

        .rodata:      168 bytes

          .text:    36557 bytes

     .noptrdata:      112 bytes

          .data:     5160 bytes

           .bss:       16 bytes


debug/macho:

          .text:    22980 bytes

     .noptrdata:       96 bytes

          .data:      456 bytes

        .rodata:       80 bytes


debug/pe:

          .text:    26004 bytes

     .noptrdata:       96 bytes

        .rodata:      288 bytes


encoding/base64:

           .bss:       32 bytes

        .rodata:       48 bytes

          .text:      846 bytes

     .noptrdata:       56 bytes


encoding/binary:

          .text:    27108 bytes

     .noptrdata:       72 bytes

           .bss:       56 bytes

        .rodata:      136 bytes


encoding/hex:

           .bss:       16 bytes

          .text:      288 bytes

     .noptrdata:       64 bytes


encoding/json:

        .rodata:      108 bytes

          .text:     2930 bytes

     .noptrdata:      128 bytes

           .bss:       80 bytes


errors:

        .rodata:       48 bytes

          .text:      744 bytes

     .noptrdata:       40 bytes

           .bss:       16 bytes


fmt:

          .text:    72010 bytes

     .noptrdata:      136 bytes

          .data:      104 bytes

           .bss:       32 bytes

        .rodata:      720 bytes


github.com/cilium/ebpf:

          .text:   170860 bytes

     .noptrdata:     1405 bytes

           .bss:      608 bytes

        .rodata:     3971 bytes

          .data:       16 bytes

      .noptrbss:        8 bytes


github.com/go-delve/delve/pkg/dwarf/frame:

          .text:    18304 bytes

     .noptrdata:       80 bytes

           .bss:        8 bytes

        .rodata:      211 bytes


github.com/go-delve/delve/pkg/dwarf/godwarf:

          .text:    40431 bytes

     .noptrdata:      144 bytes

        .rodata:      352 bytes


github.com/go-delve/delve/pkg/dwarf/line:

           .bss:       48 bytes

        .rodata:      160 bytes

          .text:    24069 bytes

     .noptrdata:       96 bytes


github.com/go-delve/delve/pkg/dwarf/loclist:

     .noptrdata:       64 bytes

        .rodata:       64 bytes

          .text:     4538 bytes


github.com/go-delve/delve/pkg/dwarf/op:

          .text:    31142 bytes

     .noptrdata:       80 bytes

           .bss:       72 bytes

        .rodata:     5313 bytes


github.com/go-delve/delve/pkg/dwarf/reader:

     .noptrdata:       72 bytes

           .bss:       16 bytes

        .rodata:       24 bytes

          .text:     8037 bytes


github.com/go-delve/delve/pkg/dwarf/regnum:

           .bss:       40 bytes

        .rodata:     2760 bytes

          .text:     3943 bytes

     .noptrdata:       48 bytes


github.com/go-delve/delve/pkg/dwarf/util:

          .text:     4028 bytes

     .noptrdata:       64 bytes

        .rodata:       96 bytes


github.com/go-delve/delve/pkg/elfwriter:

          .text:     3394 bytes

     .noptrdata:       48 bytes

        .rodata:       48 bytes


github.com/go-delve/delve/pkg/goversion:

     .noptrdata:      104 bytes

           .bss:       64 bytes

        .rodata:      160 bytes

          .text:     4415 bytes


github.com/go-delve/delve/pkg/logflags:

           .bss:       32 bytes

        .rodata:       40 bytes

          .text:     2610 bytes

     .noptrdata:      136 bytes

      .noptrbss:        3 bytes


github.com/go-delve/delve/pkg/proc:

          .text:   432477 bytes

     .noptrdata:      718 bytes

          .data:     1448 bytes

           .bss:      592 bytes

        .rodata:    10106 bytes


github.com/go-delve/delve/pkg/version:

          .text:     1509 bytes

     .noptrdata:       72 bytes

          .data:      112 bytes

        .rodata:       40 bytes


github.com/hashicorp/golang-lru/simplelru:

          .text:     3911 bytes

     .noptrdata:       32 bytes

        .rodata:      160 bytes


github.com/sirupsen/logrus:

      .noptrbss:       20 bytes

        .rodata:      696 bytes

          .text:    40175 bytes

     .noptrdata:      204 bytes

          .data:       64 bytes

           .bss:       56 bytes


go/ast:

          .text:    24407 bytes

     .noptrdata:      104 bytes

          .data:      112 bytes

        .rodata:      120 bytes


go/constant:

           .bss:        8 bytes

        .rodata:      824 bytes

          .text:    33910 bytes

     .noptrdata:       88 bytes


go/parser:

        .rodata:     1808 bytes

          .text:    78751 bytes

     .noptrdata:      136 bytes

           .bss:       32 bytes


go/printer:

          .text:    77202 bytes

     .noptrdata:      113 bytes

          .data:       24 bytes

        .rodata:     1504 bytes


go/scanner:

        .rodata:      240 bytes

          .text:    18594 bytes

     .noptrdata:       93 bytes

          .data:       24 bytes


go/token:

     .noptrdata:       72 bytes

          .data:     1376 bytes

           .bss:        8 bytes

        .rodata:      192 bytes

          .text:     7154 bytes


golang.org/x/arch/arm64/arm64asm:

        .rodata:      856 bytes

          .text:   116428 bytes

     .noptrdata:       80 bytes

           .bss:       80 bytes

          .data:    46128 bytes


golang.org/x/arch/x86/x86asm:

     .noptrdata:    29125 bytes

           .bss:      112 bytes

          .data:    20928 bytes

        .rodata:     1252 bytes

          .text:    76721 bytes


golang.org/x/sys/unix:

          .text:     1800 bytes

     .noptrdata:      128 bytes

        .rodata:       70 bytes

          .data:       80 bytes


hash/adler32:

          .text:     1013 bytes

     .noptrdata:       40 bytes


internal/bytealg:

        .rodata:       56 bytes

      .noptrbss:        8 bytes

          .text:     1462 bytes

     .noptrdata:       32 bytes


internal/cpu:

        .rodata:      500 bytes

      .noptrbss:      416 bytes

     .noptrdata:        8 bytes

           .bss:       24 bytes

          .text:     3017 bytes


internal/fmtsort:

          .text:     7443 bytes

     .noptrdata:       40 bytes

        .rodata:       40 bytes


internal/oserror:

          .text:      500 bytes

     .noptrdata:       40 bytes

           .bss:       80 bytes


internal/poll:

          .text:    31565 bytes

        .rodata:      192 bytes

     .noptrdata:      112 bytes

          .data:       96 bytes

           .bss:       64 bytes

      .noptrbss:       12 bytes


internal/reflectlite:

          .text:    13761 bytes

     .noptrdata:       32 bytes

          .data:      456 bytes

           .bss:       24 bytes

        .rodata:      496 bytes


internal/syscall/unix:

        .rodata:       72 bytes

          .text:      708 bytes

     .noptrdata:       40 bytes

      .noptrbss:        4 bytes


internal/testlog:

          .text:      827 bytes

     .noptrdata:       32 bytes

      .noptrbss:       12 bytes

           .bss:       16 bytes

        .rodata:       72 bytes


io:

     .noptrdata:      240 bytes

           .bss:      272 bytes

          .data:       56 bytes

      .noptrbss:        0 bytes

        .rodata:      128 bytes

          .text:    10824 bytes


log:

          .text:      188 bytes

     .noptrdata:       80 bytes

           .bss:        8 bytes


main:

          .text:     3002 bytes

     .noptrdata:       80 bytes

        .rodata:      104 bytes


math:

          .data:      136 bytes

           .bss:     2672 bytes

          .text:   184385 bytes

     .noptrdata:    10211 bytes

        .rodata:     2076 bytes

      .noptrbss:        2 bytes


net:

          .text:    24417 bytes

     .noptrdata:      236 bytes

          .data:      240 bytes

           .bss:      584 bytes

      .noptrbss:       16 bytes

        .rodata:       48 bytes


os:

           .bss:      264 bytes

          .data:       32 bytes

        .rodata:      352 bytes

          .text:    46276 bytes

     .noptrdata:      296 bytes

      .noptrbss:        1 bytes


path:

          .text:     9378 bytes

     .noptrdata:      136 bytes

           .bss:       48 bytes

        .rodata:       48 bytes


reflect:

      .noptrbss:        1 bytes

          .text:    97417 bytes

     .noptrdata:       72 bytes

        .rodata:     1728 bytes

          .data:      456 bytes

           .bss:      160 bytes


regexp:

        .rodata:      968 bytes

          .text:   126451 bytes

     .noptrdata:      558 bytes

           .bss:      296 bytes

      .noptrbss:       16 bytes

          .data:      816 bytes


runtime:

      .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 bytes


sort:

          .text:    13055 bytes

     .noptrdata:       32 bytes

          .data:       16 bytes

        .rodata:       24 bytes


strconv:

          .text:    45928 bytes

     .noptrdata:    17015 bytes

          .data:     1680 bytes

           .bss:       32 bytes

        .rodata:      144 bytes


strings:

          .text:    21070 bytes

     .noptrdata:      320 bytes

        .rodata:      168 bytes


sync:

        .rodata:      476 bytes

     .noptrdata:       56 bytes

           .bss:       56 bytes

      .noptrbss:        8 bytes

          .text:    14288 bytes


syscall:

     .noptrdata:      127 bytes

        .rodata:      978 bytes

      .noptrbss:       76 bytes

           .bss:      264 bytes

          .data:     2720 bytes

          .text:    33728 bytes


text/tabwriter:

          .data:       96 bytes

        .rodata:       88 bytes

          .text:     8002 bytes

     .noptrdata:       46 bytes


text/template:

          .text:   166284 bytes

     .noptrdata:      316 bytes

      .noptrbss:        8 bytes

           .bss:      176 bytes

          .data:      376 bytes

        .rodata:     3152 bytes


time:

          .text:    83290 bytes

     .noptrdata:      164 bytes

          .data:      912 bytes

           .bss:      208 bytes

      .noptrbss:       20 bytes

        .rodata:      832 bytes


unicode:

     .noptrdata:    50398 bytes

          .data:    15248 bytes

           .bss:       40 bytes

      .noptrbss:        0 bytes

          .text:    27198 bytes

注意这个程序并不完美,它只适用于 Linux/Mac,因为它依赖于 ELF。我相信您可以对 Windows PE 文件执行类似的操作,但这会花费我很多时间。


此外,这个程序忽略了 go 运行时的某些部分,但我猜这对你来说不是最重要的。


查看完整回答
反对 回复 2022-10-24
?
慕标琳琳

TA贡献1830条经验 获得超9个赞

您可以运行nm以获取二进制文件中所有对象的大小。示例:nm -S /usr/local/go/bin/gofmt。第二列是大小。


0000000000468700 000000000000011c T unicode/utf8.DecodeLastRuneInString

0000000000468240 00000000000001a6 T unicode/utf8.DecodeRune

0000000000468400 00000000000001a6 T unicode/utf8.DecodeRuneInString

0000000000468820 0000000000000157 T unicode/utf8.EncodeRune


查看完整回答
反对 回复 2022-10-24
  • 2 回答
  • 0 关注
  • 155 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信