-
Notifications
You must be signed in to change notification settings - Fork 75
PoC: Use generics instead of code gen for vectors #1412
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
base: main
Are you sure you want to change the base?
Conversation
e4cb5aa to
4fe7618
Compare
4fe7618 to
27e5315
Compare
|
|
||
| // This function will write code to the console that should be copy/pasted into frame_json.gen.go | ||
| // when changes are required. Typically this function will always be skipped. | ||
| func TestGenerateGenericArrowCode(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 really great to replace the bespoke code generation!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ryantxu if @grafana/grafana-datasources-core-services decides this is worth testing, do you think it makes sense to copy these changes to another folder/package and switch between them with an env var (similar to prom framing changes)? i can't think of another option at the moment to test these types of changes without introducing extra overhead 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@toddtreece what was the prom framing changes again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@asimpson a feature toggle was used to flip between an unmodified copy of the prometheus datasource framing code and a replacement. once the new code was determined to be ok, the old framing code was deleted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@itsmylife might have thoughts here since he helped pushed that project to completion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@toddtreece @asimpson Sorry for pretty late response. I've missed the notification.
- old logic: execute query, unmarshall it as prometheus type then convert it to data frame
- new logic: execute query, read json to convert it to data frame
The new logic was quite performance optimized but since there are many corners it's kinda hard to see what's working and what's not. So we've deiced to keep both and do the framing in both strategies. New one was the one we'd like to use but we kept the old logic as a fail safe and our north star. We've logged the issues and fixed them. Eventually we've reached the %100 match in both framing solutions. Then we safely removed the old framing solution.
I think I did the same thing for influxdb, see github.com/grafana/grafana/blob/fec7765111949e5fba4566d8e3345cd773a88569/pkg/tsdb/influxdb/influxql/parser_bench_test.go but before I finish it I think I moved to something else. (Couldn't remember trully.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@toddtreece I'm not sure how complex to do what you've suggested but it is a good idea to do it. But the code looks legit I don't think it will cause any issues (famous last words!). Let me know if I can help in any way.
|
is this faster because it can avoid the casting? |
|
@ryantxu there are a few improvements mixed in so it's probably a combination of things, but i think it's primarily related to avoiding extra allocations related to the use of |
There are already fast paths for certain types, but floats and various
others were missing, so we were falling back to a very allocation-heavy
interface{} method where every value was boxed then unboxed later.
Now that we have generic vectors we can read directly into them and
avoid a ton of allocations, which speeds things up dramatically,
especially for larger vectors.
Benchmarks for JSON unmarshalling:
```
goos: linux
goarch: amd64
pkg: github.com/grafana/grafana-plugin-sdk-go/data
cpu: AMD Ryzen 9 7950X 16-Core Processor
│ benchmark-baseline.txt │ benchmark-final.txt │
│ sec/op │ sec/op vs base │
FrameUnmarshalJSON-32 77.72µ ± ∞ ¹ 76.13µ ± ∞ ¹ ~ (p=0.421 n=5)
FrameUnmarshalJSON_FromFrameToJSON-32 74.86µ ± ∞ ¹ 76.81µ ± ∞ ¹ +2.60% (p=0.032 n=5)
FrameUnmarshalJSON_Sizes/Rows_10-32 5.345µ ± ∞ ¹ 5.065µ ± ∞ ¹ -5.24% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_100-32 25.44µ ± ∞ ¹ 22.27µ ± ∞ ¹ -12.44% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_1000-32 231.4µ ± ∞ ¹ 199.0µ ± ∞ ¹ -13.99% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_10000-32 2.523m ± ∞ ¹ 2.090m ± ∞ ¹ -17.19% (p=0.008 n=5)
FrameUnmarshalJSON_Parallel-32 25.92µ ± ∞ ¹ 25.42µ ± ∞ ¹ ~ (p=1.000 n=5)
geomean 73.85µ 68.36µ -7.43%
¹ need >= 6 samples for confidence interval at level 0.95
│ benchmark-baseline.txt │ benchmark-final.txt │
│ B/s │ B/s vs base │
FrameUnmarshalJSON-32 69.90Mi ± ∞ ¹ 71.37Mi ± ∞ ¹ ~ (p=0.421 n=5)
FrameUnmarshalJSON_FromFrameToJSON-32 72.45Mi ± ∞ ¹ 70.61Mi ± ∞ ¹ -2.54% (p=0.040 n=5)
FrameUnmarshalJSON_Sizes/Rows_10-32 93.67Mi ± ∞ ¹ 98.85Mi ± ∞ ¹ +5.53% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_100-32 118.8Mi ± ∞ ¹ 135.6Mi ± ∞ ¹ +14.21% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_1000-32 129.4Mi ± ∞ ¹ 150.5Mi ± ∞ ¹ +16.26% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_10000-32 125.4Mi ± ∞ ¹ 151.4Mi ± ∞ ¹ +20.75% (p=0.008 n=5)
geomean 98.52Mi 107.5Mi +9.07%
¹ need >= 6 samples for confidence interval at level 0.95
│ benchmark-baseline.txt │ benchmark-final.txt │
│ B/op │ B/op vs base │
FrameUnmarshalJSON-32 24.84Ki ± ∞ ¹ 24.54Ki ± ∞ ¹ -1.23% (p=0.008 n=5)
FrameUnmarshalJSON_FromFrameToJSON-32 24.84Ki ± ∞ ¹ 24.54Ki ± ∞ ¹ -1.23% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_10-32 3.328Ki ± ∞ ¹ 2.953Ki ± ∞ ¹ -11.27% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_100-32 15.50Ki ± ∞ ¹ 12.67Ki ± ∞ ¹ -18.25% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_1000-32 132.44Ki ± ∞ ¹ 98.73Ki ± ∞ ¹ -25.45% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_10000-32 1.822Mi ± ∞ ¹ 1.320Mi ± ∞ ¹ -27.59% (p=0.008 n=5)
FrameUnmarshalJSON_Parallel-32 24.84Ki ± ∞ ¹ 24.54Ki ± ∞ ¹ -1.22% (p=0.008 n=5)
geomean 41.02Ki 35.69Ki -13.00%
¹ need >= 6 samples for confidence interval at level 0.95
│ benchmark-baseline.txt │ benchmark-final.txt │
│ allocs/op │ allocs/op vs base │
FrameUnmarshalJSON-32 770.0 ± ∞ ¹ 757.0 ± ∞ ¹ -1.69% (p=0.008 n=5)
FrameUnmarshalJSON_FromFrameToJSON-32 770.0 ± ∞ ¹ 757.0 ± ∞ ¹ -1.69% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_10-32 100.00 ± ∞ ¹ 77.00 ± ∞ ¹ -23.00% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_100-32 373.0 ± ∞ ¹ 170.0 ± ∞ ¹ -54.42% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_1000-32 3.076k ± ∞ ¹ 1.073k ± ∞ ¹ -65.12% (p=0.008 n=5)
FrameUnmarshalJSON_Sizes/Rows_10000-32 30.09k ± ∞ ¹ 10.08k ± ∞ ¹ -66.50% (p=0.008 n=5)
FrameUnmarshalJSON_Parallel-32 770.0 ± ∞ ¹ 757.0 ± ∞ ¹ -1.69% (p=0.008 n=5)
geomean 1.067k 671.3 -37.10%
¹ need >= 6 samples for confidence interval at level 0.95
```
…ana-plugin-sdk-go into toddtreece/generics
… into toddtreece/generics
What this PR does / why we need it:
grafana tests
ran using k6 with two parallel queries (loki and prom). max 5000 results each.
before:
after:
Which issue(s) this PR fixes:
Fixes #
Special notes for your reviewer: