-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
provide Base.crc32c checksum and use it in checking cache staleness #18127
Conversation
should be listed in the license file and exception list in contrib/add_license_to_files.jl. |
/* compute the crc for up to seven leading bytes to bring the data pointer | ||
to an eight-byte boundary */ | ||
while (len && ((uintptr_t)next & 7) != 0) { | ||
__asm__("crc32b\t" "(%1), %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.
should fall back to the software version for _COMPILER_MICROSOFT_
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.
Done.
Fixed the license file and updated the tests. |
@test isfile(joinpath(dir, "FooBar.ji")) | ||
|
||
sleep(2) # wait to make sure file modification date changes |
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 might need a bit more than 2 seconds to ensure the date changes
(not serious)
We could use __cpuid and _mm_crc32_u64 with MS compilers, rather than inline asm. |
JL_DLLEXPORT uint32_t jl_crc32c(uint32_t crc, const void *buf, size_t len) | ||
{ | ||
return | ||
#ifdef __x86_64__ |
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.
HW_CRC ?
…ystems have at least 1s resolution
(Speaking of future optimizations, ARMv8 also has a |
Yay, tests are green. |
@@ -29,6 +29,7 @@ for exceptions. | |||
|
|||
Julia includes code from the following projects, which have their own licenses: | |||
|
|||
- [crc32c.c](http://stackoverflow.com/questions/17645167/implementing-sse-4-2s-crc32c-in-software) (CRC-32c checksum code by Mark Adler) [[ZLib](https://opensource.org/licenses/Zlib)]. |
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.
Missing newline and -
?
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, the line has a newline and a -
. Maybe the diff format is confusing?
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.
Yes, sorry, I'm gonna go clean my glasses.
@StefanKarpinski, @vtjnash, any comment? |
I'm still against using a checksum to validate files. Remember too that with precompile, you will pay this cost m*n^2 times, so even a small cost quickly adds up and requires moving many megabytes of extra data which may not be local (the precompile .ji files are all supposed to be local) |
@vtjnash, the files whose timestamps don't match but whose checksums match will typically be small The number of times that this occurs is irrelevant, because in the cases where you run the same checksum a large number of times you are also loading the module from a cache a large number of times. |
We can easily fix that bug in BinDeps rather than working around it here. I don't see any reason loading a module should be slower than doing CRC over the sources. In fact, I think that loading the module should be less work. I don't find it terribly convincing that this only affects a small number of cases, for me that's also a negative. Another very strong negative, IMO, is that doing touch or save in my editor won't trigger a rebuild. With this change, I now need to know where to find a hidden cache file and delete it if something goes wonky. That violates the goal of the cache being fully transparent. |
Changing the timestamp without changing the content shouldn't trigger a rebuild. Timestamps aren't a great proxy for matching content. This will make .ji files more portable and easier to deploy as part of prebuilding Julia along with sets of packages. |
Timestamps aren't simply a proxy for content, they are part of the content, and one that is easy for the user to influence. In that regard, I could perhaps accept Deployment is a different process with different requirements. I don't see any reason to couple it to the behavior of precompile. |
Because the timestamp of a Julia file doesn't change the end-result behavior of the code contained in it whatsoever? |
Hah. That assumes that the compiler is pure with respect to the universe, which is nonsense. It's not even best effort; I would give it a grade of: "tries to be fairly predictable if everything goes well". But fortunately a changed timestamp is a strong indicator that the user did intend to change something, so we can mostly recover from the inaccuracy of the rest of the system. |
|
BinDeps set the "this dependency has changed and needs to be rebuilt" flag. It's not the fault of base that we honor this flag, nor the fault of the original author (since the capability didn't exist at the time). But seriously, fix BinDeps. I'm not trying to read minds, because I don't have to. I can simply read the filesystem metadata that has been the standard for build systems, noting that the frequent failure there is that it is not strict enough, and arguing that we shouldn't react by making our heuristics weaker. Nobody ever wished that it might not be possible to get
|
#17845 (comment) wasn't about BinDeps. You're equating filesystem metadata with "indicator that the user did intend to change something," when they're often not connected at all.
The existence of |
Rebuilding a false positive is fine as long as it doesn't get stuck repeatedly attempting to the update. It is not acceptable for a build system to have "not often" false negatives which have no easy recourse for the user to fix them.
not at all, it agrees with me perfectly. First of all, I actually intend to write a ccache-like too for Julia, although designed around Julia's semantics so it will be completely different. |
Okay, I'm convinced. |
I have to call b.s. on this statement. Are you really claiming that reading, parsing and compiling a Julia file will take less time than computing a CRC on the file? |
no, I'm claiming that doing a crc on the source would add a significant percentage to the time to load the precompile file, so it would add a bit of unpredictable uncertainty to the load time. In other-words, I'm committing to making precompile loading much faster :) |
fwiw, please don't delete this branch, as having CRC code is likely to be useful (for example, we could be using it to validate that the .ji files aren't truncated or corrupted.) |
@vtjnash, yes, that was my thought. |
Maybe I should open another PR with just the CRC? |
sgtm. If you didn't, I was planning on doing it myself. Probably not a huge cost, but I would prefer – flr the sake of startup time – to either make the table data fully static, or lazy initialize it (using |
This fixes #17845: to reduce the chance of false positives when checking cache staleness, it also checks a CRC-32c checksum of the file if the timestamp doesn't match. (That is, the file is considered stale if
timestamp mismatch && checksum mismatch
).The performance impact seems to be negligible. In the common case where the timestamps match, the checksum is never computed at all, and in any case the computation of a checksum seems to be orders of magnitude faster than the time to load the cache file.
I used Mark Adler's (@madler)
BSD-licensedzlib-licensed CRC-32c implementation that he posted on StackOverflow, which includes both software and hardware-accelerated versions (the latter for SSE4.2 hardware). Adler seems to be someone who knows what he is doing with checksum algorithms, so I was happy to see he posted usable code. His code seems to be pretty fast (well over an order of magnitude faster than @andrewcooke's implementation in CRC.jl, which Andrew said is comparable to zlib; see also andrewcooke/CRC.jl#5). @baruch did some benchmarking and he found that Adler's implementation was one of the fastest. I don't see much point in re-implementing it in Julia.Because of the existence of hardware support, CRC-32c seems like the most sensible choice of checksum algorithm, so I didn't really look at alternatives.
It also seems like a good idea to export the
crc32c
checksum function, since this is pretty generally useful functionality to have, but I wanted to get feedback first.