-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Two's complement representation for decimals #10051
Conversation
Some preliminary benchmark results for decimal addition:
|
If this changes long decimal representation, how do we address connectors compatibility? |
e262860
to
68d4e5d
Compare
I don't think there's a good way around that. We'll probably have to make this a backward compatibility breaking change. It's unfortunate that we chose the current representation when we first introduced decimals, and that we didn't have the facilities to support arbitrary object types other than Slice back then (which seems to introduce non-trivial performance issues). On the positive side, since we're changing the stack type, any connector that doesn't support the new representation will just fail loudly instead of producing incorrect results. There may be ways to do it in a backward compatible way, though -- I haven't spent too much time thinking about it yet, though. If you have any thoughts on how we might do it, please comment. |
68d4e5d
to
f122343
Compare
How about exposing method like |
Not sure how that would work. The type can only support one “stack” and block type |
@kokosing actually i am in favor of backwards incompatible approach. |
I am sorry I haven't read the code yet. I was under impression that "stack" type didn't change but only encoding. |
4af2e9d
to
62e2b15
Compare
Update benchmarks:
|
62e2b15
to
f013a2c
Compare
f013a2c
to
5ed15c3
Compare
c83cc0b
to
a902aeb
Compare
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.
Reviewed Int128 and Int128Math so far.
public static int compare(long leftHigh, long leftLow, long rightHigh, long rightLow) | ||
{ | ||
int comparison = Long.compare(leftHigh, rightHigh); | ||
if (comparison == 0) { |
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.
Make it branchless?
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.
You mean like this?
int high = Long.compare(leftHigh, rightHigh);
int low = Long.compareUnsigned(leftLow, rightLow);
return high == 0 ? low : high;
It's not clear that that's actually generates branchless code (need to check the assembly), and it has extra cos of computing low unconditionally if the VM is not smart enough to move the computation inside the high == 0
check if it's not able to generate branchless code.
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.
Rather something like:
int highComparison = Long.compare(leftHigh, rightHigh);
int lowComparison = Long.compareUnsigned(leftLow, rightLow);
comparison = highComparison + ~(highComparison & 1) * lowComparison;
But I guess you can put it on the todo list and benchmark it later
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.
highComparison & 1
That may not work. Long.compare is not guaranteed to return -1, 0 or 1. According to its javadocs, it will return "a value less than 0 if x < y", "a value greater than 0 if x > y".
It would need to be adjusted to something like:
int high = Long.compare(aHigh, bHigh);
int low = Long.compareUnsigned(aLow, bLow);
int mask = ~(high | -high) >> 31;
int comparison = high + (mask & low);
81a6a9a
to
692eab1
Compare
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.
Went through all of it. Looks good.
core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java
Outdated
Show resolved
Hide resolved
core/trino-main/src/test/java/io/trino/operator/aggregation/TestDecimalAverageAggregation.java
Outdated
Show resolved
Hide resolved
core/trino-spi/src/main/java/io/trino/spi/type/LongDecimalType.java
Outdated
Show resolved
Hide resolved
d281075
to
a07e645
Compare
a07e645
to
dbcc6cb
Compare
Both branches call the same method, so one of them is not needed.
dbcc6cb
to
8cd1e8c
Compare
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.
Mostly minor comments
core/trino-main/src/main/java/io/trino/operator/aggregation/DecimalSumAggregation.java
Outdated
Show resolved
Hide resolved
core/trino-main/src/main/java/io/trino/operator/aggregation/DecimalSumAggregation.java
Outdated
Show resolved
Hide resolved
core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java
Outdated
Show resolved
Hide resolved
core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java
Show resolved
Hide resolved
8cd1e8c
to
014aef2
Compare
Also, use a dedicated class to represent long decimals instead of Slice.
Avoid using intermediate BigIntegers when decoding long decimals from Parquet and RCBinary
014aef2
to
05ac13c
Compare
@martint Excuse me. I have a question. According to you provided micro benchmark. In some cases, the addition, multiply and division operators have regression. Do the trino fixed these issue? or how to fix them. |
No description provided.