Skip to content

libnet/internal/resolvconf: optimize Generate() without text/template#50428

Merged
thaJeztah merged 4 commits intomoby:masterfrom
thaJeztah:resolvconf_notemplate
Jul 17, 2025
Merged

libnet/internal/resolvconf: optimize Generate() without text/template#50428
thaJeztah merged 4 commits intomoby:masterfrom
thaJeztah:resolvconf_notemplate

Conversation

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Jul 16, 2025

libnet/internal/resolvconf: optimize Generate() without text/template

Rewrite this function to not use text/template, which is ~74× faster,
~25× less memory, and ~56× fewer allocations.

Before/After:

BenchmarkGenerate-10       42550     27439 ns/op    18083 B/op    394 allocs/op
BenchmarkGenerate-10     3148328       373 ns/op      712 B/op      7 allocs/op

- Human readable description for the release notes

- A picture of a cute animal (not mandatory but encouraged)

@dmcgowan
Copy link
Member

Thanks for opening this! We will definitely need the buildkit version in 29. Should we just take this in here and in a buildkit fork for 29 and what repo might this logic move to eventually?

@thaJeztah thaJeztah force-pushed the resolvconf_notemplate branch from d93c53d to b5b37b5 Compare July 17, 2025 06:06
Comment on lines -74 to +72
return fmt.Sprintf("host(%s)", ed.Addr)
return "host(" + ed.Addr.String() + ")"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated this one in the last iteration as well to shave off some bits;

Before/after;

    BenchmarkGenerate-10     2617477       453 ns/op      736 B/op      8 allocs/op
    BenchmarkGenerate-10     3148328       373 ns/op      712 B/op      7 allocs/op

Comment on lines -422 to +462
fields := strings.Fields(line)

// Strip blank lines and comments.
if len(fields) == 0 || fields[0][0] == '#' || fields[0][0] == ';' {
if line == "" || line[0] == '#' || line[0] == ';' {
return
}

fields := strings.Fields(line)
if len(fields) == 0 {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed an extra commit for these; it occurred to me that we were calling string.Fields() before checking if it was an empty line or comment; better to skip early.

Comment on lines +513 to +515
k, v, hasSep := strings.Cut(opt, ":")
if k == "ndots" {
if !hasSep || v == "" {
continue
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly here; no need to strconv.Atoi() empty values.

Copy link
Contributor

@robmry robmry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! LGTM.

Comment on lines +296 to +297
b.WriteString(rc.md.Header + "\n")
b.WriteByte('\n')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not worth changing, but ...

Suggested change
b.WriteString(rc.md.Header + "\n")
b.WriteByte('\n')
b.WriteString(rc.md.Header)
b.WriteString("\n\n")

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went back-and-forth a bit on this one; contemplated to just append \n\n to the write string, but then chose to stick with a separate b.WriteByte('\n') after it, to align more with all other places we insert a newline; I'll probably keep this one as-is for now.

    goos: darwin
    goarch: arm64
    pkg: github.com/docker/docker/daemon/libnetwork/internal/resolvconf
    cpu: Apple M1 Pro
    BenchmarkGenerate
    BenchmarkGenerate-10    	   42550	     27439 ns/op	   18083 B/op	     394 allocs/op
    PASS

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Rewrite this function to not use text/template, which is ~74× faster,
~25× less memory, and ~56× fewer allocations.

Before/After:

    BenchmarkGenerate-10       42550     27439 ns/op    18083 B/op    394 allocs/op
    BenchmarkGenerate-10     3148328       373 ns/op      712 B/op      7 allocs/op

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
@thaJeztah
Copy link
Member Author

CI is green (Windows failure is unrelated); I'll push that last nit, and merge when build is happy

@thaJeztah thaJeztah force-pushed the resolvconf_notemplate branch from b5b37b5 to 60a3a28 Compare July 17, 2025 09:41
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Comment on lines -533 to +529
type errSystem struct{ error }
// systemErr implements [github.com/docker/docker/errdefs.ErrSystem].
type systemErr struct{ error }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As CI is restarting; I pushed one more commit that made linting fail on BuildKit; only changing the name of the type, so should have no impact otherwise.

@thaJeztah
Copy link
Member Author

Build and unit-tests are happy; bringing this one in

@thaJeztah thaJeztah merged commit 9af9d27 into moby:master Jul 17, 2025
153 of 155 checks passed
@thaJeztah thaJeztah deleted the resolvconf_notemplate branch July 17, 2025 10:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants