refactor(profiler): centralize compression logic#3529
Conversation
d674907 to
6eed203
Compare
BenchmarksBenchmark execution time: 2025-05-19 18:34:33 Comparing candidate commit 442e89c in PR branch Found 5 performance improvements and 1 performance regressions! Performance is the same for 49 metrics, 1 unstable metrics. scenario:BenchmarkInjectW3C-24
scenario:BenchmarkSetTagString-24
scenario:BenchmarkSetTagStringPtr-24
scenario:BenchmarkSingleSpanRetention/with-rules/match-all-24
scenario:BenchmarkSingleSpanRetention/with-rules/match-half-24
scenario:BenchmarkStartSpan-24
|
6eed203 to
65bef4d
Compare
3c9c178 to
fc4682f
Compare
| compressors: make(map[ProfileType]compressor), | ||
| } | ||
| types := slices.Collect(maps.Keys(cfg.types)) | ||
| // We need to manually add executionTrace to the list of profile types to be |
darccio
left a comment
There was a problem hiding this comment.
It looks great. I'm curious about the performance impact by code layout changes that we seem to have in the benchmarks.
Yeah, so I raised #3530 to check if there is general flakiness here, but I wasn't able to reproduce results like the ones above, so I suspect that we're indeed seeing code layout changes here. Which ... is pretty annoying 😞. It means we can't really use benchmark platform to spot smaller regression. Note: This isn't the fault of the platform, and it's great that it raises awareness for this. But I'm starting to think we need some code layout randomization for Go if we want to be serious about continuous benchmarking 🤔. |
nsrip-dd
left a comment
There was a problem hiding this comment.
LGTM. I tested this out with a toy app and confirmed that the profiles make it through intact and I can view them in the UI.
I'm curious to see how you'll implement recompression. I managed to bash something together (https://go.dev/play/p/YeHeuCgfUjl) that'd fit the current interface. If I recall from past experience, going through io.Pipe can be kinda slow. So definitely factor that in when testing out recompression if you take that approach.
|
|
||
| func TestRunProfile(t *testing.T) { | ||
| // TODO(felixge): These tests are directly calling the internal runProfile() | ||
| // function which is brittle. We should refactor them to use the public API. |
There was a problem hiding this comment.
I'm trying to remember why I didn't already delete this test... I'm happy to look into it
For historical reasons, the profiler has used varying levels of compression for different profile types (no compression, gzip-1 and gzip-6). This has been identified as target for cost optimization, see PROF-11815. Refactor the compression related code in order to pave the path for introducing a new compression strategy, which will most likely be based on zstd. This patch should not have any observable impact. Profiles are expected to be uploaded with exactly the same compression settings as before, and the performance is expected to stay exactly the same as well. Introduce a dedicated compressor for each profile type that handles converting the profile data produced by it from the existing compression (gzip-1 or no compression) to the desired output compression. Update delta profiles and expGoroutineWaitProfile to perform their gzip-6 compression in the compressor for their profile type, rather than doing it themselves. A few TestRunProfile tests had to be modified because they were not explicitly declaring the profile types they were testing when initializing the profiler, which caused panics due to their compressors being uninitialized.
fc4682f to
442e89c
Compare
Our non-delta heap, block, and mutex profiles are getting double-compressed. That is, they are gzip-compressed, and if you decompress them then you get another gzip-compressed blob, which is in turn a compressed pprof file. This is due to a bug introduced by #3529. In that PR we reworked our compression logic in order to support re-compression (into zstd in particular). We incorrectly decided whether a given profile type is a delta profile by just checking whether there are delta values for the profile, without checking whether delta profiling is actually enabled. As a result, when delta profiling is disabled we use the delta profling _enabled_ logic, where we assume the input data is uncomprossed and then gzip-compress it.
Our non-delta heap, block, and mutex profiles are getting double-compressed. That is, they are gzip-compressed, and if you decompress them then you get another gzip-compressed blob, which is in turn a compressed pprof file. This is due to a bug introduced by #3529. In that PR we reworked our compression logic in order to support re-compression (into zstd in particular). We incorrectly decided whether a given profile type is a delta profile by just checking whether there are delta values for the profile type, without checking whether delta profiling is actually enabled. As a result, when delta profiling is disabled we use the delta profling enabled logic, where we assume the input data is uncomprossed and then gzip-compress it.
For historical reasons, the profiler has used varying levels of
compression for different profile types (no compression, gzip-1 and
gzip-6). This has been identified as target for cost optimization,
see PROF-11815.
Refactor the compression related code in order to pave the path for
introducing a new compression strategy, which will most likely be based
on zstd.
This patch should not have any observable impact. Profiles are expected
to be uploaded with exactly the same compression settings as before, and
the performance is expected to stay exactly the same as well.
Introduce a dedicated compressor for each profile type that handles
converting the profile data produced by it from the existing compression
(gzip-1 or no compression) to the desired output compression.
Update delta profiles and expGoroutineWaitProfile to perform their
gzip-6 compression in the compressor for their profile type, rather than
doing it themselves.
A few TestRunProfile tests had to be modified because they were not
explicitly declaring the profile types they were testing when
initializing the profiler, which caused panics due to their compressors
being uninitialized.
Reviewer's Checklist
golangci-lint runlocally.