Skip to content
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

hash(Type) is not stable across runs #39

Closed
gafter opened this issue Mar 29, 2023 · 7 comments · Fixed by #44
Closed

hash(Type) is not stable across runs #39

gafter opened this issue Mar 29, 2023 · 7 comments · Fixed by #44
Labels

Comments

@gafter
Copy link
Member

gafter commented Mar 29, 2023

hashing a type is not fast. That's why some people cache it in a static map. This code should either avoid hashing a type, or should store it in a static map.

@gafter
Copy link
Member Author

gafter commented Mar 29, 2023

Oh, the hash of a type probably isn't stable between julia runs, as it is based on object identity. Which means that an object with a precomputed hash that involves the hash of a type likely will not get the same hash code as another "equivalent" object created in a different run of julia.

@gafter gafter changed the title hash(Type) is not fast hash(Type) is not stable across runs Mar 29, 2023
gafter referenced this issue in JuliaServices/AutoHashEqualsCached.jl Mar 29, 2023
@gafter
Copy link
Member Author

gafter commented Mar 29, 2023

It actually is stable within a particular build of Julia it seems.

@gafter
Copy link
Member Author

gafter commented Mar 30, 2023

This might be better:

# compute the hash of any given type by hashing the fully qualified name of that
# type.  But do it only once, and cache the result in a generated function.
@generated function _hashed_type_name(x::Type{T}) where {T}
    hash(string(T))
end

See discussion on the Julia slack.

@gafter
Copy link
Member Author

gafter commented Mar 30, 2023

I wonder how Union types decide what order to print their members in.

julia> Union{Union{A{String}, A{Int}}, Int}
Union{Int64, A{Int64}, A{String}}

julia> Union{Int64, A{Int64}, A{String}}
Union{Int64, A{Int64}, A{String}}

@gafter
Copy link
Member Author

gafter commented Mar 30, 2023

@NHDaly points out that can change even during a single run due to aliasing. This, then:

@generated function _hashed_type_name(x::Type{T}) where {T}
    iobuf = IOBuffer()
    show(IOContext(iobuf, :compact => false), T) # This IOContext avoids alias search.
    type_string = String(resize!(iobuf.data, iobuf.size))
    hash(type_string)
end

(https://github.com/RelationalAI/raicode/blob/772b0918321e63d66a9ef290897b7c6d91bf72ee/packages/MurmurHash3F/src/MurmurHash3F.jl#L255-L262)

@gafter
Copy link
Member Author

gafter commented Jun 1, 2023

julia> module A; struct B; x; end; end
Main.A

julia> Base.hash(A.B)
0xedeca5aeea4dd690

julia> module A; struct B; x; end; end
WARNING: replacing module A.
Main.A

julia> Base.hash(A.B)
0x11bcb3aac1326f85

@gafter gafter transferred this issue from JuliaServices/AutoHashEqualsCached.jl Aug 18, 2023
@gafter gafter added the up next label Aug 18, 2023
@gafter
Copy link
Member Author

gafter commented Aug 19, 2023

We have #44 to address this for clients who care.

@gafter gafter linked a pull request Aug 19, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant