-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
Use lookup table when calculating CRC16 XMODEM #733
Conversation
* I borrowed it from redis/lettuce@b921931
@mp911de @allanwax @marcosnils @xetorthio @marcosnils @xetorthio |
public class JedisClusterCRC16 { | ||
public final static int polynomial = 0x1021; // Represents x^16+x^12+x^5+1 | ||
|
||
public static final int LOOKUP_TABLE[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, |
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 this private. I've missed to make this constant private in lettuce.
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.
@mp911de Oh, others can break table. Thanks!
Looks good. |
👍 awesome!. It should definitely go into 2.6 |
Use lookup table when calculating CRC16 XMODEM
Merged to master and 2.6 |
@marcosnils Thanks for merging! |
crc = ((crc << 8) ^ LOOKUP_TABLE[((crc >> 8) ^ (b & 0xFF)) & 0xFF]) & you need >>> instead of >> or sign extension will happen. 'C' and java Allan Wax On 9/12/2014 7:00 AM, Jungtaek Lim wrote:
|
You can probably eliminate the final '& 0xFFFF' crc = (crc << 8) ^ LOOKUP_TABLE[((crc >>> 8) ^ bytes[i]) & 0x00FF]; On 9/12/2014 1:59 AM, Mark Paluch wrote:
|
@allanwax Would you please provide "edge-case" examples of current implementation? |
Btw, 16384 is a power of 2, so we can apply optimization to modulo, "% 16384" to "& (16384 - 1)", when we really need to apply optimizations as much as possible. |
I can't provide any edge cases where there is a failure but I've tested the code modification above and I get the same results. It saves the final '& 0xFFFF' in the loop. Now '&' is a very fast instruction but millions of them will add up. As long as there are no mathematical operations (i.e. only boolean operations) then there are no functional issues. I have no problem leaving the code as is since it does work and is faster than before. Lots of other things to work on. |
@allanwax Actually I don't mean final '& 0xFFFF' but sign extension. |
Sign extension MAY affect the result in the shift since a double shift The performance issue is only that we're adding an and at the end of On 9/15/2014 6:03 PM, Jungtaek Lim wrote:
|
@allanwax @mp911de (revised : I made a mistake during calculation with "crc >> 8", revised one time)
Using uint16_t in C, (crc << 8) discards previous CRC value’s upper 1 byte, but our code just shifts byte At first, we names (crc << 8) to (A). Inside of calculation of array index, (crc >> 8) occurs sign extension so crc’s leftmost 8 bit fills with sign bit and other bits shifts, especially 9 ~ 16 bit shifts to 1 ~ 8 bit. -- (B) We reference LOOKUP_TABLE with (D), -- (E). BUT, we already confirmed that sign extension doesn’t affect result, and core calculation uses only 2 bytes of previous CRC. tl;dr. So, applying @allanwax suggestion makes same result to current, and it's faster. Please correct me if I am wrong. |
Yep, some 5-10% |
Sounds good to me |
Also, the compiler may or may not be smart enough to transform 'return getCRC16(key) % 16384' into 'return getCRC16(key) & (16384 - 1) // 0x3FFF' If not, the above change may help speed things up by a tiny amount. |
I've ran a benchmark to see it helps. Before100883 ops After104535 ops It seems to help! |
'Q a new' ??? |
Actually, I did not know that I sent this comment. So just ignore it. |
Related to #729.
I borrowed it from redis/lettuce@b921931
Thanks @mp911de!
And thanks @allanwax for considering better algorithm!