Skip to content

Reduce compression memory use with map[string]uint16 #852

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 1, 2018

Conversation

tmthrgd
Copy link
Collaborator

@tmthrgd tmthrgd commented Nov 30, 2018

This PR switches the packing code to use a map[string]uint16 for storing compression pointers while keeping support for external callers who pass in a map[string]int. This reduces the per-entry memory consumption of the compression map by 25%. ((16+2)/(16+8) = 0.75).

compressionMap is passed quite specifically as a value rather than a pointer because RR.pack is an interface method call which would cause it to escape and be heap allocated if it were to be a pointer. As maps are internally represented by a pointer to the runtime's hmap struct, the size of compressionMap is only 16-bytes anyway.

The benchmarks show a notable improvement in both memory use (alloc/op) and performance (time/op) for packing messages where multiple records are present.

name                    old time/op    new time/op    delta
MsgLengthPack-12          1.41µs ± 9%    1.46µs ±10%     ~     (p=0.353 n=10+10)
PackDomainName-12          128ns ± 0%     137ns ± 1%   +6.72%  (p=0.000 n=6+10)
PackA-12                  39.0ns ± 1%    40.1ns ± 1%   +2.69%  (p=0.000 n=8+8)
PackMX-12                 69.6ns ± 1%    72.4ns ± 1%   +4.05%  (p=0.000 n=10+9)
PackAAAAA-12              37.9ns ± 1%    40.0ns ± 1%   +5.68%  (p=0.000 n=10+9)
PackMsg-12                1.01µs ± 5%    0.95µs ± 1%   -5.85%  (p=0.000 n=10+10)
PackMsgOnlyQuestion-12     168ns ± 0%     176ns ± 1%   +4.94%  (p=0.000 n=6+10)
PackMsgMassive-12         67.8µs ±10%    55.1µs ±10%  -18.70%  (p=0.000 n=10+10)

name                    old alloc/op   new alloc/op   delta
MsgLengthPack-12            576B ± 0%      528B ± 0%   -8.33%  (p=0.000 n=10+10)
PackDomainName-12          0.00B          0.00B          ~     (all equal)
PackA-12                   0.00B          0.00B          ~     (all equal)
PackMX-12                  0.00B          0.00B          ~     (all equal)
PackAAAAA-12               0.00B          0.00B          ~     (all equal)
PackMsg-12                  256B ± 0%      208B ± 0%  -18.75%  (p=0.000 n=10+10)
PackMsgOnlyQuestion-12     0.00B          0.00B          ~     (all equal)
PackMsgMassive-12         23.1kB ± 0%    19.0kB ± 0%  -17.88%  (p=0.000 n=10+10)

name                    old allocs/op  new allocs/op  delta
MsgLengthPack-12            3.00 ± 0%      3.00 ± 0%     ~     (all equal)
PackDomainName-12           0.00           0.00          ~     (all equal)
PackA-12                    0.00           0.00          ~     (all equal)
PackMX-12                   0.00           0.00          ~     (all equal)
PackAAAAA-12                0.00           0.00          ~     (all equal)
PackMsg-12                  2.00 ± 0%      2.00 ± 0%     ~     (all equal)
PackMsgOnlyQuestion-12      0.00           0.00          ~     (all equal)
PackMsgMassive-12           12.0 ± 0%      12.0 ± 0%     ~     (all equal)

Updates #652 (see #652 (comment)).

Edit: This is similar to #820 but for packing.

map[string]uint16 uses 25% less memory per-entry than a map[string]int
(16+2)/(16+8) = 0.75. All entries in the compression map are bound by
maxCompressionOffset which is 14-bits and fits within a uint16.
@tmthrgd tmthrgd requested a review from miekg November 30, 2018 14:07
@codecov-io
Copy link

codecov-io commented Nov 30, 2018

Codecov Report

Merging #852 into master will increase coverage by 0.08%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #852      +/-   ##
==========================================
+ Coverage   57.96%   58.05%   +0.08%     
==========================================
  Files          42       42              
  Lines       10675    10690      +15     
==========================================
+ Hits         6188     6206      +18     
+ Misses       3398     3396       -2     
+ Partials     1089     1088       -1
Impacted Files Coverage Δ
dns.go 62.5% <ø> (ø) ⬆️
zmsg.go 50.75% <100%> (ø) ⬆️
msg_helpers.go 56.93% <100%> (ø) ⬆️
defaults.go 66.21% <100%> (ø) ⬆️
msg.go 79.2% <100%> (+1.21%) ⬆️
privaterr.go 67.56% <100%> (ø) ⬆️
server.go 65.96% <0%> (-0.24%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6b6e08b...9391be8. Read the comment docs.

@miekg
Copy link
Owner

miekg commented Dec 1, 2018 via email

@tmthrgd
Copy link
Collaborator Author

tmthrgd commented Dec 1, 2018

Only PackMsgMassive really exercises the compression code that well. The other benchmarks usually only include a single name with three labels multiple times, meaning the compression map has only three entries and it barely has any effect on the overall performance. I think real world results would be more positive than anything but PackMsgMassive.

If you look at the benchmarks, the increases are on the order of a few nanoseconds (and I believe come solely down to an extra few nil checks), while PackMsgMassive shows an improvement of over ten microseconds. I think something like Consul(?) would see a strong improvement here.

@tmthrgd tmthrgd merged commit 470f08e into miekg:master Dec 1, 2018
@tmthrgd tmthrgd deleted the compression-uint16 branch December 1, 2018 22:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants