-
Notifications
You must be signed in to change notification settings - Fork 102
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
Handle negative varint #56
Conversation
@@ -374,30 +375,73 @@ Pbf.prototype = { | |||
} | |||
}; | |||
|
|||
function readVarintRemainder(val, pbf) { | |||
var buf = pbf.buf, b; | |||
function readVarintRemainder(l, u, p) { |
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.
This function uses single character variables names to keep it under 600 characters. Longer functions are not inlined by v8, which drastically decreases performance.
@@ -74,12 +76,12 @@ test('readVarint64', function(t) { | |||
test('readVarint & writeVarint handle really big numbers', function(t) { | |||
var buf = new Pbf(); | |||
var bigNum1 = Math.pow(2, 60); | |||
var bigNum2 = Math.pow(2, 69); |
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.
This is not a valid number to serialize in varint
. The 64th bit on a signed integer is the sign bit. If we try to use the full 10th bytes, there is no way to distinguish the sign bit from the rest of the number.
Unfortunately, binary literals aren't added until ES2015, which, IMHO, would make this easier to read / understand. Any thoughts on using constants as a pseudo-binary literal? E.g., // Instead of 0x80
var b10000000 = parseInt('10000000', 2); |
Whoa. I somehow missed all the notifications for this PR, sorry for a late reply! Since this is a substantial change, it will probably affect benchmark numbers — how do those look? Also, how much of a breaking change the |
The This did seem to affect the benchmarks somewhat. I think it may be because of the larger functions.
I'm not sure on the precise impacts because the benchmarks are very noisy on my machine--possibly due to other processes running. |
@kjvalencik interesting! Are you relying on this in your use case? I wonder whether it's something that could justify a 13% write performance drop, or something that we could document as a limitation instead. |
I'm not relying on it anywhere. Since we are always going to a However, my use case does depend on putting negative numbers in |
Can we drop the |
I pushed a version without the Interestingly, it must have been something about handling
If you would like to go forward with that, I will add some documentation in the README and update this PR. Thanks! |
} | ||
} | ||
|
||
if (toNum(low, high, true) < Math.abs(val)) { |
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.
Narrowed it down to this line causing the performance issue. Changing this to the following fixes the speed regression.
if (val >= 0x8000000000000000 || val < -0x8000000000000000) {
throw new Error('Given varint doesn\'t fit into 10 bytes');
}
decode vector tile with pbf x 920 ops/sec ±1.04% (89 runs sampled)
encode vector tile with pbf x 613 ops/sec ±1.11% (83 runs sampled
@kjvalencik fantastic! Let's clean up, rebase and it's good to merge. I wonder what caused the speedup though — the vector tile in the bench shouldn't have many big varints if at all. |
@mourner I was thinking about backwards compatibility. Even if I remove the Instead, what do you think about flipping it to |
@mourner Flipped |
@@ -120,9 +120,9 @@ function compileFieldRead(ctx, field) { | |||
case 'bool': return prefix + 'Boolean()'; | |||
case 'enum': | |||
case 'uint32': | |||
case 'uint64': | |||
case 'uint64': return prefix + 'Varint(false)'; |
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.
Should we just use readVarint()
for more compact code, or will it affect performance?
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.
I'm not aware of any performance cost of coercing to boolean
. 👍
Can you rebase on master please? |
Yes, but I won't have a chance until Monday. Thanks! |
-> #60 |
Resolves #55