-
Notifications
You must be signed in to change notification settings - Fork 573
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
[improvement] Some performance related changes to evaluate #1426
Changes from 3 commits
277a4aa
4cd4d3c
92a353c
bb51f19
73d9f63
c2e21ab
d0b8c0e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,9 +21,11 @@ import ( | |
"bytes" | ||
"errors" | ||
"math" | ||
"slices" | ||
"strconv" | ||
|
||
"github.com/ClickHouse/ch-go/proto" | ||
"golang.org/x/exp/maps" | ||
) | ||
|
||
func Enum(chType Type, name string) (Interface, error) { | ||
|
@@ -47,19 +49,33 @@ func Enum(chType Type, name string) (Interface, error) { | |
enum.iv[values[i]] = proto.Enum8(v) | ||
enum.vi[proto.Enum8(v)] = values[i] | ||
} | ||
enum.minEnum = int8(slices.Min(maps.Keys(enum.vi))) | ||
enum.maxEnum = int8(slices.Max(maps.Keys(enum.vi))) | ||
enum.continuous = (enum.maxEnum-enum.minEnum)+1 == int8(len(enum.vi)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For Enum8 non-continuous & continous could both use a 256 bit bitmap (only 32 bytes, could skip heap by being in struct as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I understand your suggestion. Do you have some (semi-code) example of how you would use that, and which library? (Since I don't know of any bitmap implementations in the Golang standard library itself.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to use library, can be done in loop above, something like
then when checking existence There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gave this solution some thought, but I think its defeating the purpose. The whole idea was to skip the map lookup ( If you think it does, I can try creating a benchmark and compare the different solutions. But would need to find a bit of time to put in that effort. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe the expense on the CPU would be different between a standard map type and the bitmap. It should be similarly as fast as the integer bounds check. If the solution works as-is then I'm okay with keeping it, if it's invalid then the server will throw an error. Most clients are already fairly in sync with their data model, especially with enums. I wouldn't want to hold the PR back due to this, we can iterate on it later There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤦♂️ of course. Somehow I had a map in my mind due to the bitmap I'll make the changes accordingly and verify |
||
return &enum, nil | ||
} | ||
enum := Enum16{ | ||
iv: make(map[string]proto.Enum16, len(values)), | ||
vi: make(map[proto.Enum16]string, len(values)), | ||
chType: chType, | ||
name: name, | ||
// to be updated below, when ranging over all index/enum values | ||
minEnum: math.MaxInt16, | ||
maxEnum: math.MinInt16, | ||
} | ||
|
||
for i := range values { | ||
enum.iv[values[i]] = proto.Enum16(indexes[i]) | ||
enum.vi[proto.Enum16(indexes[i])] = values[i] | ||
k := int16(indexes[i]) | ||
|
||
enum.iv[values[i]] = proto.Enum16(k) | ||
enum.vi[proto.Enum16(k)] = values[i] | ||
if k < enum.minEnum { | ||
enum.minEnum = k | ||
} | ||
if k > enum.maxEnum { | ||
enum.maxEnum = k | ||
} | ||
} | ||
enum.continuous = (enum.maxEnum-enum.minEnum)+1 == int16(len(enum.vi)) | ||
return &enum, nil | ||
} | ||
|
||
|
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.
No need to create slice of keys (& bring in exp/maps dependency)
Instead you can have one loop over keys (either using plain
range enum.vi
orrange maps.Key(enum.vi)
from golang stdlib, not sure if the latter is still too recent in golang for us to use in this library), & calculate min/max at the same timeThere 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.
Agree, I can make those changes if the solution in general is accepted (something I wasn't sure about).
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.
just noticed
range values
loop above, can calc min/max in thereThere 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.
Changed this for
Enum16
, but will wait a bit for theEnum8
case for a response here: https://github.com/ClickHouse/clickhouse-go/pull/1426/files#r1905195485