-
Couldn't load subscription status.
- Fork 143
Speed up (pre)compile and load times #681
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
Conversation
src/HDF5.jl
Outdated
| native_size === Csize_t(2) ? (return Int16) : | ||
| native_size === Csize_t(4) ? (return Int32) : | ||
| native_size === Csize_t(8) ? (return Int64) : | ||
| throw(KeyError(class_id, is_signed, native_size)) |
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 sure this line (and similar in the other branches) is actually necessary — the final check size-8 case in principle could just be the else-case of the size-4 ternary. Thoughts?
| (H5T_FLOAT, nothing, Csize_t(4)) => Float32, | ||
| (H5T_FLOAT, nothing, Csize_t(8)) => Float64, | ||
| ) | ||
| function _hdf5_type_map(class_id, is_signed, native_size) |
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.
👍
| fun, propids = hdf5_obj_open[objtype] | ||
| props = [p_create(prop; pv...) for prop in propids] | ||
| obj = fun(parent, path, props...) | ||
| if objtype == H5I_DATASET |
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 also bet this is just simply also far faster
| UTF8_ATTRIBUTE_PROPERTIES[] = p_create(H5P_ATTRIBUTE_CREATE) | ||
| h5p_set_char_encoding(UTF8_ATTRIBUTE_PROPERTIES[].id, H5T_CSET_UTF8) | ||
|
|
||
| rehash!(hdf5_type_map, length(hdf5_type_map.keys)) |
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.
yay, glad we can get rid of this now
It might then just be worth it to add type annotations where necessary to help the compiler with inference in these cases, instead of (or in addition to) I kind of think adding the line Is not that elegant, given it is current experimental status, however the precompilation latency reduction (10% faster) and improved inference are very welcome. Overall, very nice PR. Still reviewing some final changes, but 👍 |
Yeah, doing some more systematic review of types and inference's understanding of the code is something worth doing but wasn't as easy of low-hanging fruit. And just because I was maybe a bit unclear, the inference change of |
|
|
||
| a_create(parent::Union{HDF5File, HDF5Object}, name::String, dtype::HDF5Datatype, dspace::HDF5Dataspace) = HDF5Attribute(h5a_create(checkvalid(parent).id, name, dtype.id, dspace.id), file(parent)) | ||
|
|
||
| function _prop_set!(p::HDF5Properties, name::Symbol, val, check::Bool = true) |
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.
Is this check arg really needed, It seems a bit superfluous? I think the rationale is that we can squeeze a bit of perf without having to error check in internal use, but perhaps the compiler is good enough that we don't need such fine grained tuning.
Perhaps these should all be written like (not sure if that helps the compiler guess the right branch?)
if class == H5P_FILE_CREATE
elseif class == H5P_FILE_ACCESS
elseif class H5P_GROUP_CREATE
....
else
error(....
endOTOH the way to code is written as is, is pretty clear.
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.
EDIT:
Actually NVM I don't think it's that feasible given the way the code is structured as is, and would remove some important error checking in the if-clauses.
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.
Is this check arg really needed, It seems a bit superfluous?
The reason I added it was to maintain the current behavior — p_create does not error even if you pass it properties that are not appropriate for a particular property class, while setindex! did (by way of just throwing when the underlying h5p_set_* function errored). The two functions now set false and true, respectively, to maintain that.
Co-authored-by: Mustafa M <[email protected]>
|
Awesome ! |
|
I kinda wonder if we should just disable the integration tests, it's pretty annoying to see red X on PRs that pass. |
This PR does two primary things with the goal of reducing load time:
Dicts that are rehashed on init are eliminated, replaced withif-elsechains at their use or in new internal helper functions. This was motivated by looking at the output of@snoopi using HDF5(where I started Julia withjulia --compiled-modules=no) and noticed that many of the methods near the end with largest times wereDictmethods.One minor advantage of doing this is that property names can now be valid for multiple HDF5 classes. For instance, the
__init__code had to callh5p_set_char_encodingforASCII_ATTRIBUTE_PROPERTIESandUTF8_ATTRIBUTE_PROPERTIESbecause:char_encodingwas already mapped toH5P_LINK_CREATEso couldn't be used for these two properties which areH5P_ATTRIBUTE_CREATEproperties. After replacing theDictlookup, though, the_prop_set!function can have a:char_encodingcase forH5P_ATTRIBUTE_CREATEwithout any conflicts.To evaluate the effectiveness of this change, I've timed loading (
using HDF5) with a missing precompiled cache, loading with a valid precompiled cache, and the time to run the entire test suite (with the precompiled cache active). The times comparing current master versus the first commit from this PR (run with near-latest Julia, average and std over 10 runs) show:Running the same timing tests again:
I've noticed at least one case where type inference improves despite the lower optimization level:
getindex(::Union{HDF5File, HDF5Group}, ::String)used to infer asAnybut with this PR is inferred returning anHDF5Object.My hacked together timing script can be found in this gist