Skip to content
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

Enable default gzip compression for otlp exporters #4587

Closed
jack-berg opened this issue Dec 20, 2021 · 7 comments
Closed

Enable default gzip compression for otlp exporters #4587

jack-berg opened this issue Dec 20, 2021 · 7 comments

Comments

@jack-berg
Copy link
Member

Describe the solution you'd like
Recently there was a spec PR about enabling gzip compression by default for OTLP in the SDK. The TC concluded that the default OTLP settings are optimized for exporting to a local collector, where compression is not useful.

The collector does not have a default OTLP export location, and it is much more common to export to a remote network address than to another collector running locally.

I propose that we enable gzip compression by default for OTLP exporters. Compression is great for clients and servers alike. Its better if users have to opt out of compression than opting in, as it will improve the likelihood of casual users having it enabled.

Additional context
Reminder that according to the spec, all server components MUST support gzip compression. So changing this behavior will not impact spec compliant OTLP receivers.

Compression ratio varies based on shape of the payload, but in some simple local tests of OTLP payloads I've seen anywhere from 15% to 60+% reduction in payload size. This can have a very significant positive impact on performance!

@bogdandrutu
Copy link
Member

Compression ratio varies based on shape of the payload, but in some simple local tests of OTLP payloads I've seen anywhere from 15% to 60+% reduction in payload size. This can have a very significant positive impact on performance!

100% agree with you, but I would like to understand the CPU cost as well.

@jack-berg
Copy link
Member Author

There are several dimensions that impact the performance benefit / cost of compression. Geo distribution of client and server: clients with long round trips to servers pay a steep price for unnecessary bytes they send. Clients can be put under memory pressure from data queuing up while awaiting the trips, which can then become CPU pressure. So somewhat paradoxically, spending extra CPU cycles on compression can result in lower overall CPU pressure. Additionally, the randomness of the data can change the equation. Highly random data won't compress as well, but will still incur the CPU cost. Still, despite the fact that compression isn't always the right decision, it is the right decision in the vast majority of cases. And the default behavior really should aim to provide good results most of the time.

It seems quite challenging to incorporate network latency and varying payload shapes into a performance test suite. Perhaps a simplified analysis would suffice? What if we just tried to characterize the CPU cost of compression, but not the overall impact of smaller payloads? I.e. try to answer the question: "how long does it take to gzip compress 1kb"? At least that gives you an idea of the price you pay in the worst case scenario in which smaller payloads provide little benefit.

@jack-berg
Copy link
Member Author

jack-berg commented Jan 3, 2022

I've done some benchmarks of various grpc compression algorithms on a branch here.

Notes:

  • Tested gzip, zstd, and snappy compression
  • Tested small and large log, trace, and metric payloads.
  • Small payloads are on the order of ~200 bytes.
  • Large payloads are on the order of ~70kb.
  • Compression ratio varies based on the randomness of the payload, so see the branch for how I define the payloads.

Raw Results:

cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkCompressors
BenchmarkCompressors/sm_log_request/raw_bytes_198/compressed_bytes_188/compressor_gzip
BenchmarkCompressors/sm_log_request/raw_bytes_198/compressed_bytes_188/compressor_gzip-12         	   29317	     37722 ns/op
BenchmarkCompressors/sm_log_request/raw_bytes_198/compressed_bytes_187/compressor_zstd
BenchmarkCompressors/sm_log_request/raw_bytes_198/compressed_bytes_187/compressor_zstd-12         	  119768	      9205 ns/op
BenchmarkCompressors/sm_log_request/raw_bytes_198/compressed_bytes_216/compressor_snappy
BenchmarkCompressors/sm_log_request/raw_bytes_198/compressed_bytes_216/compressor_snappy-12       	 1000000	      1067 ns/op
BenchmarkCompressors/lg_log_request/raw_bytes_72869/compressed_bytes_23214/compressor_gzip
BenchmarkCompressors/lg_log_request/raw_bytes_72869/compressed_bytes_23214/compressor_gzip-12     	    1174	   1007992 ns/op
BenchmarkCompressors/lg_log_request/raw_bytes_72869/compressed_bytes_24163/compressor_zstd
BenchmarkCompressors/lg_log_request/raw_bytes_72869/compressed_bytes_24163/compressor_zstd-12     	    1213	   1012678 ns/op
BenchmarkCompressors/lg_log_request/raw_bytes_72869/compressed_bytes_32261/compressor_snappy
BenchmarkCompressors/lg_log_request/raw_bytes_72869/compressed_bytes_32261/compressor_snappy-12   	    8281	    143830 ns/op
BenchmarkCompressors/sm_trace_request/raw_bytes_199/compressed_bytes_172/compressor_gzip
BenchmarkCompressors/sm_trace_request/raw_bytes_199/compressed_bytes_172/compressor_gzip-12       	   28714	     35336 ns/op
BenchmarkCompressors/sm_trace_request/raw_bytes_199/compressed_bytes_174/compressor_zstd
BenchmarkCompressors/sm_trace_request/raw_bytes_199/compressed_bytes_174/compressor_zstd-12       	  126903	      9431 ns/op
BenchmarkCompressors/sm_trace_request/raw_bytes_199/compressed_bytes_189/compressor_snappy
BenchmarkCompressors/sm_trace_request/raw_bytes_199/compressed_bytes_189/compressor_snappy-12     	 1000000	      1013 ns/op
BenchmarkCompressors/lg_trace_request/raw_bytes_52894/compressed_bytes_8035/compressor_gzip
BenchmarkCompressors/lg_trace_request/raw_bytes_52894/compressed_bytes_8035/compressor_gzip-12    	    1760	    659759 ns/op
BenchmarkCompressors/lg_trace_request/raw_bytes_52894/compressed_bytes_7645/compressor_zstd
BenchmarkCompressors/lg_trace_request/raw_bytes_52894/compressed_bytes_7645/compressor_zstd-12    	    2912	    433809 ns/op
BenchmarkCompressors/lg_trace_request/raw_bytes_52894/compressed_bytes_11998/compressor_snappy
BenchmarkCompressors/lg_trace_request/raw_bytes_52894/compressed_bytes_11998/compressor_snappy-12 	   12096	     97968 ns/op
BenchmarkCompressors/sm_metric_request/raw_bytes_271/compressed_bytes_215/compressor_gzip
BenchmarkCompressors/sm_metric_request/raw_bytes_271/compressed_bytes_215/compressor_gzip-12      	   29433	     37771 ns/op
BenchmarkCompressors/sm_metric_request/raw_bytes_271/compressed_bytes_215/compressor_zstd
BenchmarkCompressors/sm_metric_request/raw_bytes_271/compressed_bytes_215/compressor_zstd-12      	  113664	     10551 ns/op
BenchmarkCompressors/sm_metric_request/raw_bytes_271/compressed_bytes_245/compressor_snappy
BenchmarkCompressors/sm_metric_request/raw_bytes_271/compressed_bytes_245/compressor_snappy-12    	  817531	      1358 ns/op
BenchmarkCompressors/lg_metric_request/raw_bytes_87604/compressed_bytes_19664/compressor_gzip
BenchmarkCompressors/lg_metric_request/raw_bytes_87604/compressed_bytes_19664/compressor_gzip-12  	     796	   1496601 ns/op
BenchmarkCompressors/lg_metric_request/raw_bytes_87604/compressed_bytes_19525/compressor_zstd
BenchmarkCompressors/lg_metric_request/raw_bytes_87604/compressed_bytes_19525/compressor_zstd-12  	    1254	    983527 ns/op
BenchmarkCompressors/lg_metric_request/raw_bytes_87604/compressed_bytes_25134/compressor_snappy
BenchmarkCompressors/lg_metric_request/raw_bytes_87604/compressed_bytes_25134/compressor_snappy-12         	    3933	    264181 ns/op

Results with some additional analysis:

Request Compressor Raw bytes Compressed bytes Compression ratio Ns / op Mb compressed / second Mb saved / second
lg_log_request gzip 72869 23214 3.14 1007992 72.29 49.26
lg_metric_request gzip 87604 19664 4.46 1496601 58.54 45.40
lg_trace_request gzip 52894 8035 6.58 659759 80.17 67.99
sm_log_request gzip 198 188 1.05 37722 5.25 0.27
sm_metric_request gzip 271 215 1.26 37771 7.17 1.48
sm_trace_request gzip 199 172 1.16 35336 5.63 0.76
lg_log_request snappy 72869 32261 2.26 143830 506.63 282.33
lg_metric_request snappy 87604 25134 3.49 264181 331.61 236.47
lg_trace_request snappy 52894 11998 4.41 97968 539.91 417.44
sm_log_request snappy 198 216 0.92 1067 185.57 -16.87
sm_metric_request snappy 271 245 1.11 1358 199.56 19.15
sm_trace_request snappy 199 189 1.05 1013 196.45 9.87
lg_log_request zstd 72869 24163 3.02 1012678 71.96 48.10
lg_metric_request zstd 87604 19525 4.49 983527 89.07 69.22
lg_trace_request zstd 52894 7645 6.92 433809 121.93 104.31
sm_log_request zstd 198 187 1.06 9205 21.51 1.20
sm_metric_request zstd 271 215 1.26 10551 25.68 5.31
sm_trace_request zstd 199 174 1.14 9431 21.10 2.65

The last column Mb saved / second is interesting. It calculates the number of megabytes that are saved from being sent over the wire for each second spent compressed payloads of the given type with the given algorithm.

Snappy doesn't compress as well or zstd or gzip, but is much faster is the best bang for your buck if the process is CPU bound. If the process is network bound, gzip and zstd are likely better options as they offer better compression.

However, gzip is the only compression algo required by the spec and should perform reasonably well for most people.

Edited 1/4/2022: Changed compression ratio from (compressed bytes - raw bytes) / compressed bytes to raw bytes / compressed bytes. Also sorted table so that results are grouped by their compression algo.

@jpkrohling
Copy link
Member

That's great info, I think this should be part of the documentation for this feature. The only thing I would request is to get the formula for the "compress ratio" changed so that it shows 1-(compressed bytes / raw bytes). Having a compression rate of more than 100% seems odd ;-)

@jack-berg
Copy link
Member Author

I defined the compression ratio as (compressed bytes - raw bytes) / compressed bytes. I think 1-(compressed bytes / raw bytes) is a good formula too. Not a ton of consensus on how best to represent it. I think I'll update it to raw bytes / compressed bytes, which I've anecdotally seen referenced more often than other formulas. This yields numbers like 4.46, which can be interpreted as "4.46:1", or "4.46 to 1 compression". This feels pretty intuitive to me.

@jpkrohling
Copy link
Member

"4.46 to 1" is great, way better than a percentage.

tigrannajaryan pushed a commit that referenced this issue Feb 3, 2022
Change OTLP gRPC exporter to use `gzip` compression by default. If this is merged, I can followup with the OTLP HTTP exporter to use `gzip` by default as well.

**Link to tracking Issue:** 
#4587 

**Testing:**
- Added benchmarks comparing different compression algorithms.
- Updated `configgrpc_test.go` to validate default behavior

**Documentation:** 
Added details to `/config/configgrpc/README.md` with benchmark results and notes on compression.
@jack-berg
Copy link
Member Author

Resolved with #4632.

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

No branches or pull requests

3 participants