client_golang icon indicating copy to clipboard operation
client_golang copied to clipboard

Parse HTTP response directly

Open importhuman opened this issue 3 years ago • 8 comments

Was something like this required for #977? (I'm aware tests are failing, will look into it more)

Got the following benchmark results (used the existing benchmark test in client_test.go, not sure why delta is nil)

name              old time/op    new time/op    delta
Client/4KB-12       62.7µs ± 0%   137.4µs ± 0%   ~     (p=1.000 n=1+1)
Client/50KB-12       119µs ± 0%     132µs ± 0%   ~     (p=1.000 n=1+1)
Client/1000KB-12    1.44ms ± 0%    0.13ms ± 0%   ~     (p=1.000 n=1+1)
Client/2000KB-12    2.68ms ± 0%    0.14ms ± 0%   ~     (p=1.000 n=1+1)

name              old alloc/op   new alloc/op   delta
Client/4KB-12       20.5kB ± 0%    18.2kB ± 0%   ~     (p=1.000 n=1+1)
Client/50KB-12       136kB ± 0%      18kB ± 0%   ~     (p=1.000 n=1+1)
Client/1000KB-12    2.11MB ± 0%    0.02MB ± 0%   ~     (p=1.000 n=1+1)
Client/2000KB-12    4.21MB ± 0%    0.02MB ± 0%   ~     (p=1.000 n=1+1)

name              old allocs/op  new allocs/op  delta
Client/4KB-12         74.0 ± 0%     128.0 ± 0%   ~     (p=1.000 n=1+1)
Client/50KB-12         101 ± 0%       137 ± 0%   ~     (p=1.000 n=1+1)
Client/1000KB-12       595 ± 0%       135 ± 0%   ~     (p=1.000 n=1+1)
Client/2000KB-12     1.10k ± 0%     0.14k ± 0%   ~     (p=1.000 n=1+1)

Thank you!

importhuman avatar Jul 18 '22 17:07 importhuman

cc @bboreham @kakkoyun can you please review if this is along correct lines?

importhuman avatar Jul 26 '22 13:07 importhuman

No, I don't expect the code to get much shorter when implementing this. In particular code like this which you removed: https://github.com/prometheus/client_golang/pull/1090/files#diff-aa9bfd1a638fbb706f8e8920297902937011160319d9679add5dca56e5ab8277L145-L153 is important to handle timeouts, and will need some functional replacement.

Possibly calling resp.Body.Close() will still work, but I think you will need a goroutine watching for context cancellation in order to do this.

bboreham avatar Jul 26 '22 17:07 bboreham

@bboreham will this work? I didn't use a select statement since this flow doesn't use a done channel. Apologies for the late update.

importhuman avatar Aug 11 '22 16:08 importhuman

Sorry for not closing this sooner, I've been unable to devote time. If this is high priority, happy to let someone else pick this up and help them. Will still try to finish it.

importhuman avatar Aug 31 '22 16:08 importhuman

Benchmark results:

main branch:

goos: linux
goarch: amd64
pkg: github.com/prometheus/client_golang/api
cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
BenchmarkClient/4KB-12         	   19268	     55355 ns/op	   20532 B/op	      74 allocs/op
BenchmarkClient/50KB-12        	   10000	    100465 ns/op	  135893 B/op	     101 allocs/op
BenchmarkClient/1000KB-12      	    1003	   1201450 ns/op	 2112968 B/op	     595 allocs/op
BenchmarkClient/2000KB-12      	     542	   2535752 ns/op	 4214170 B/op	    1097 allocs/op
PASS
ok  	github.com/prometheus/client_golang/api	5.644s

This branch:

goos: linux
goarch: amd64
pkg: github.com/prometheus/client_golang/api
cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
BenchmarkClient/4KB-12         	    8221	    137427 ns/op	   18519 B/op	     131 allocs/op
BenchmarkClient/50KB-12        	    8016	    136149 ns/op	   18442 B/op	     139 allocs/op
BenchmarkClient/1000KB-12      	    7760	    136296 ns/op	   18307 B/op	     138 allocs/op
BenchmarkClient/2000KB-12      	    8731	    137935 ns/op	   18318 B/op	     138 allocs/op
PASS
ok  	github.com/prometheus/client_golang/api	5.793s

Benchstat:

name              old time/op    new time/op    delta
Client/4KB-12       55.4µs ± 0%   137.4µs ± 0%   ~     (p=1.000 n=1+1)
Client/50KB-12       100µs ± 0%     136µs ± 0%   ~     (p=1.000 n=1+1)
Client/1000KB-12    1.20ms ± 0%    0.14ms ± 0%   ~     (p=1.000 n=1+1)
Client/2000KB-12    2.54ms ± 0%    0.14ms ± 0%   ~     (p=1.000 n=1+1)

name              old alloc/op   new alloc/op   delta
Client/4KB-12       20.5kB ± 0%    18.5kB ± 0%   ~     (p=1.000 n=1+1)
Client/50KB-12       136kB ± 0%      18kB ± 0%   ~     (p=1.000 n=1+1)
Client/1000KB-12    2.11MB ± 0%    0.02MB ± 0%   ~     (p=1.000 n=1+1)
Client/2000KB-12    4.21MB ± 0%    0.02MB ± 0%   ~     (p=1.000 n=1+1)

name              old allocs/op  new allocs/op  delta
Client/4KB-12         74.0 ± 0%     131.0 ± 0%   ~     (p=1.000 n=1+1)
Client/50KB-12         101 ± 0%       139 ± 0%   ~     (p=1.000 n=1+1)
Client/1000KB-12       595 ± 0%       138 ± 0%   ~     (p=1.000 n=1+1)
Client/2000KB-12     1.10k ± 0%     0.14k ± 0%   ~     (p=1.000 n=1+1)

Slightly worse for 4 and 50 KB, much better for 1000 and 2000 KB.


Failing tests:

Currently, they are failing due to a different error message. I have slightly changed the flow of the code to be in line what is currently in main branch, reading the response body after checking the status code. Are we allowed to change the expected error message? My concern is doing it would impact users who have structured their code with the current expected error messages.

importhuman avatar Sep 05 '22 16:09 importhuman

cc @bboreham @kakkoyun

importhuman avatar Sep 08 '22 16:09 importhuman

I've just noticed that the code calls the JSON parser twice to read each request. Once in `apiClientImpl.Do: https://github.com/prometheus/client_golang/blob/618194de6ad3db637313666104533639011b470d/api/prometheus/v1/api.go#L1140

and once in the individual API methods like Query: https://github.com/prometheus/client_golang/blob/618194de6ad3db637313666104533639011b470d/api/prometheus/v1/api.go#L859

Then, different data types make nested calls: https://github.com/prometheus/client_golang/blob/618194de6ad3db637313666104533639011b470d/api/prometheus/v1/api.go#L584

I suspect the first two could be merged without major change, but the last kind needs the code rewritten in "streaming" style to avoid building an intermediate buffer.

bboreham avatar Sep 18 '22 14:09 bboreham

Thanks for the detailed feedback! I don't have the answers currently, will update as I look into these issues more.

importhuman avatar Sep 20 '22 12:09 importhuman

Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

stale[bot] avatar Nov 23 '22 03:11 stale[bot]