Skip to content

Instantly share code, notes, and snippets.

@benburkert
Created June 14, 2017 17:47
Show Gist options
  • Save benburkert/beb730564223d6f5e475e1c1cfff8262 to your computer and use it in GitHub Desktop.
Save benburkert/beb730564223d6f5e475e1c1cfff8262 to your computer and use it in GitHub Desktop.
BenchmarkAppend memory profile
$ go test -run XXX -bench=BenchmarkAppend -memprofile mem.out -memprofilerate 1 golang.org/x/net/dns/dnsmessage
$ go tool pprof -alloc_space -list dnsmessage dnsmessage.test mem.out
Total: 124.64MB
ROUTINE ======================== golang.org/x/net/dns/dnsmessage.(*Message).AppendPack in /Users/benburkert/src/golang.org/x/net/dns/dnsmessage/message.go
0 124.54MB (flat, cum) 99.92% of Total
. . 639: //
. . 640: // DNS lookups are typically done over UDP, and RFC 1035 states that UDP
. . 641: // DNS packets can be a maximum of 512 bytes long. Without compression,
. . 642: // many DNS response packets are over this limit, so enabling
. . 643: // compression will help ensure compliance.
. 23.35MB 644: compression := map[string]int{}
. . 645:
. . 646: for _, q := range m.Questions {
. . 647: var err error
. 101.19MB 648: msg, err = q.pack(msg, compression)
. . 649: if err != nil {
. . 650: return nil, &nestedError{"packing Question", err}
. . 651: }
. . 652: }
. . 653: for _, a := range m.Answers {
ROUTINE ======================== golang.org/x/net/dns/dnsmessage.(*Question).pack in /Users/benburkert/src/golang.org/x/net/dns/dnsmessage/message.go
0 101.19MB (flat, cum) 81.18% of Total
. . 1069: Type Type
. . 1070: Class Class
. . 1071:}
. . 1072:
. . 1073:func (q *Question) pack(msg []byte, compression map[string]int) ([]byte, error) {
. 101.19MB 1074: msg, err := packName(msg, q.Name, compression)
. . 1075: if err != nil {
. . 1076: return msg, &nestedError{"Name", err}
. . 1077: }
. . 1078: msg = packType(msg, q.Type)
. . 1079: return packClass(msg, q.Class), nil
ROUTINE ======================== golang.org/x/net/dns/dnsmessage.BenchmarkAppendPack in /Users/benburkert/src/golang.org/x/net/dns/dnsmessage/message_test.go
2kB 124.54MB (flat, cum) 99.92% of Total
. . 387: }
. . 388: }
. . 389:}
. . 390:
. . 391:func BenchmarkAppendPack(b *testing.B) {
. 1.62kB 392: msg := largeTestMsg()
2kB 2kB 393: buf := make([]byte, 0, 512)
. . 394:
. . 395: b.ReportAllocs()
. . 396:
. . 397: for i := 0; i < b.N; i++ {
. 124.54MB 398: if _, err := msg.AppendPack(buf[:0]); err != nil {
. . 399: b.Fatal(err)
. . 400: }
. . 401: }
. . 402:}
. . 403:
ROUTINE ======================== golang.org/x/net/dns/dnsmessage.largeTestMsg in /Users/benburkert/src/golang.org/x/net/dns/dnsmessage/message_test.go
1.62kB 1.62kB (flat, cum) 0.0013% of Total
. . 404:func largeTestMsg() Message {
. . 405: return Message{
. . 406: Header: Header{Response: true, Authoritative: true},
. . 407: Questions: []Question{
. . 408: {
256B 256B 409: Name: "foo.bar.example.com.",
. . 410: Type: TypeA,
. . 411: Class: ClassINET,
. . 412: },
. . 413: },
. . 414: Answers: []Resource{
. . 415: &AResource{
. . 416: ResourceHeader: ResourceHeader{
. . 417: Name: "foo.bar.example.com.",
. . 418: Type: TypeA,
. . 419: Class: ClassINET,
. . 420: },
192B 192B 421: A: [4]byte{127, 0, 0, 1},
. . 422: },
128B 128B 423: &AResource{
. . 424: ResourceHeader: ResourceHeader{
. . 425: Name: "foo.bar.example.com.",
. . 426: Type: TypeA,
. . 427: Class: ClassINET,
. . 428: },
192B 192B 429: A: [4]byte{127, 0, 0, 2},
. . 430: },
. . 431: },
. . 432: Authorities: []Resource{
. . 433: &NSResource{
. . 434: ResourceHeader: ResourceHeader{
. . 435: Name: "foo.bar.example.com.",
. . 436: Type: TypeNS,
. . 437: Class: ClassINET,
. . 438: },
192B 192B 439: NS: "ns1.example.com.",
. . 440: },
128B 128B 441: &NSResource{
. . 442: ResourceHeader: ResourceHeader{
. . 443: Name: "foo.bar.example.com.",
. . 444: Type: TypeNS,
. . 445: Class: ClassINET,
. . 446: },
192B 192B 447: NS: "ns2.example.com.",
. . 448: },
. . 449: },
. . 450: Additionals: []Resource{
. . 451: &TXTResource{
. . 452: ResourceHeader: ResourceHeader{
. . 453: Name: "foo.bar.example.com.",
. . 454: Type: TypeTXT,
. . 455: Class: ClassINET,
. . 456: },
192B 192B 457: Txt: "So Long, and Thanks for All the Fish",
. . 458: },
. . 459: &TXTResource{
. . 460: ResourceHeader: ResourceHeader{
. . 461: Name: "foo.bar.example.com.",
. . 462: Type: TypeTXT,
. . 463: Class: ClassINET,
. . 464: },
192B 192B 465: Txt: "Hamster Huey and the Gooey Kablooie",
. . 466: },
. . 467: },
. . 468: }
. . 469:}
. . 470:
ROUTINE ======================== golang.org/x/net/dns/dnsmessage.packName in /Users/benburkert/src/golang.org/x/net/dns/dnsmessage/message.go
0 101.19MB (flat, cum) 81.18% of Total
. . 950: }
. . 951:
. . 952: // Miss. Add the suffix to the compression table if the
. . 953: // offset can be stored in the available 14 bytes.
. . 954: if len(msg) <= int(^uint16(0)>>2) {
. 101.19MB 955: compression[name[i:]] = len(msg)
. . 956: }
. . 957: }
. . 958: }
. . 959: return append(msg, 0), nil
. . 960:}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment