-
-
Notifications
You must be signed in to change notification settings - Fork 27
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
Speeding up C implementation #42
base: main
Are you sure you want to change the base?
Conversation
For information, here is a summary of the benchmark results.
Finally, FreeBSD uses clang, so if built with GCC 13, the results will be different.
|
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.
There's a lot going on here which I worry will make it harder to maintain and for others to understand. I would prefer that each generated C extension be fully explicit and self-contained, allowing them to be loaded individually and easily be reviewed/audited.
@@ -27,6 +16,5 @@ void Init_crc12_3gpp_ext() | |||
rb_ext_ractor_safe(true); | |||
#endif | |||
|
|||
rb_undef_method(cCRC12_3GPP, "update"); | |||
rb_define_method(cCRC12_3GPP, "update", Digest_CRC12_3GPP_update, 1); |
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.
The reason why we undef
and re-define the update
method is to prevent warnings from ruby -w
, which some people apparently use for testing/production. This solution will need to keep this, or prove it doesn't cause warnings under ruby -w
.
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 will fix it to do undef
.
ext/digest/crc12_3gpp/extconf.rb
Outdated
|
||
have_header("stdint.h") | ||
have_header('stddef.h') | ||
|
||
slice_size = ENV["RUBY_DIGEST_CRC_ENABLE_SLICING_BY_16"].to_i > 0 ? 16 : 8 |
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.
Could we use if
/else
with an implicit return value instead of ternary expressions? Also could we use shorter environment variable names, like RUBY_DIGEST_CRC_SLICE_SIZE
?
ext/digest/crc16_dnp/extconf.rb
Outdated
|
||
have_header("stdint.h") | ||
have_header('stddef.h') | ||
|
||
slice_size = ENV["RUBY_DIGEST_CRC_ENABLE_SLICING_BY_16"].to_i > 0 ? 16 : 8 |
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.
Prefer to use if
/else
with implicit return values over ternary expressions.
ext/digest/crc16_kermit/extconf.rb
Outdated
|
||
have_header("stdint.h") | ||
have_header('stddef.h') | ||
|
||
slice_size = ENV["RUBY_DIGEST_CRC_ENABLE_SLICING_BY_16"].to_i > 0 ? 16 : 8 |
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.
Prefer to use if
/else
with an implicit return value instead of ternary expressions. Also this logic seems to be repeated in each file. Maybe it should be moved into gentable.rb
?
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.
Maybe it should be moved into
gentable.rb
?
Yes, I will.
ext/digest/gentable.rb
Outdated
@@ -0,0 +1,125 @@ | |||
using Module.new { |
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.
Let's not use refinements or monkey-patching here. I think a regular method named bitreflrect()
is good enough.
ext/digest/crc/crc_ext.c
Outdated
\ | ||
for (int i = 0; i < 256; i++) { \ | ||
crc_int_t n = V(table_initialize)(model->bitwidth, i); \ | ||
for (int j = 0; j < 8; j++) { \ |
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.
Same here.
ext/digest/crc/crc_ext.c
Outdated
table[0][i] = n; \ | ||
} \ | ||
\ | ||
for (int s = 1; s < SLICE_SIZE; s++) { \ |
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.
and here.
ext/digest/crc/crc_ext.c
Outdated
} \ | ||
\ | ||
for (int s = 1; s < SLICE_SIZE; s++) { \ | ||
for (int i = 0; i < 256; i++) { \ |
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.
and here.
ext/digest/crc.h
Outdated
#if !defined(HAVE_RB_EXT_RACTOR_SAFE) | ||
static inline void ruby_digest_crc_ensure_ractor_main(const char *mesg) | ||
{ | ||
(void)mesg; |
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.
Not sure what the purpose is of this statement? Seems to be a no-op?
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 used to suppress cc -Wextra
warnings about unused variables.
ext/digest/crc/crc_ext.c
Outdated
#define BUILD_TABLE_CORE_DECL(V) \ | ||
const crc_int_t modified_poly = V(adapt)(model->bitwidth, model->polynomial); \ | ||
\ | ||
for (int i = 0; i < 256; i++) { \ |
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.
Also an old school optimization trick is to always define your loop variables above/outside of your loop. This prevents dumb compilers for re-allocating space on the stack for nested for loop index variables.
Summary of changes:.
Tables are still generated at build time of the installation. |
@@ -15,52 +15,42 @@ | |||
*/ |
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.
According to https://github.com/tpircher/pycrc#copyright-of-the-generated-source-code, the generated code can be treated as public domain.
Do we need any addenda as a digest-crc project to prevent misidentification?
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 can't see it because it's out of sight.
digest-crc/ext/digest/crc12_3gpp/crc12_3gpp.c
Lines 1 to 15 in 91ee75f
/** | |
* \file | |
* Functions and types for CRC checks. | |
* | |
* Generated on Sat Feb 29 02:30:42 2020 | |
* by pycrc v0.9.2, https://pycrc.org | |
* using the configuration: | |
* - Width = 12 | |
* - Poly = 0x80f | |
* - XorIn = 0x000 | |
* - ReflectIn = False | |
* - XorOut = 0x000 | |
* - ReflectOut = True | |
* - Algorithm = table-driven | |
*/ |
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.
Probably not. We may need to change the wording to "Originally generated" or "Derived from", since I made some modifications by adding custom typdef
s.
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'll not do anything in this PR as I believe you will make this change if necessary.
Switch from Sarwate's algorithm to byte-order free Slicing-by-16. Each table data file was generated by `ext/digest/gentable.rb`. In addition, the inspection string for rspec, which was previously 10 bytes, is extended to 19 bytes. This is to check the Slicing-by-16 loop, which processes in 16-byte units.
Table data is to be prepared in advance. Also, I forgot to mention in the last change, "Slicing-by-16" is always used. |
Switch from Sarwate's algorithm to byte-order free Slicing-by-16.
Each table data file is generated by
extconf.rb
.In addition, the inspection string, which was previously 10 bytes, is extended to 19 bytes.
This is to check the slicing-by-16 loop, which processes in 16-byte units.