-
Notifications
You must be signed in to change notification settings - Fork 108
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
Associative Map Example #343
base: main
Are you sure you want to change the base?
Conversation
All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the ℹ️ Googlers: Go here for more info. |
And i made the bot sad again because i committed based on top of the wrong branch. 😂 |
Benchmarks
Dex
JuliaThe OrderedCollections.LittleDict is not quite the list dict implemented here, but it is close. julia> using OrderedCollections, BenchmarkTools
julia> const full_data = [([10ii, ii]=>ii) for ii in 1:256];
julia> const littledict = LittleDict(full_data);
julia> const hashdict = Dict(full_data);
julia> @btime littledict[$[1280, 128]];
330.862 ns (0 allocations: 0 bytes)
julia> @btime hashdict[$[1280, 128]];
73.187 ns (0 allocations: 0 bytes)
julia> @btime hash($([1280, 128]))
64.405 ns (0 allocations: 0 bytes)
0x71191e98f759495d |
If the hash is the performance bottleneck, should we use a cheaper one instead of the PRNG-grade threefry? |
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.
Nice! BTW I wouldn't use %time
for benchmarks, because it only executes the code once. When it only takes a few us or ns, you should use %bench
, which will execute it a number of times to get a more accurate estimate.
Finally, there is one caveat which is that for some reason even the most trivial functions seem to take around 2us when ran in %bench
, so it is unlikely that you will ever see values in the ranged of nanoseconds, even if that's the true cost. I suspect it's a problem with our benchmarking infrastructure, or it might be a cost of doing an FFI call from Haskell, but I didn't have time to investigate.
:p tryGetHashDict big_hashdict [210, 20] | ||
:p tryGetListDict big_listdict [210, 20] | ||
|
||
' ## Wrap under a common interface |
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 would like help working out what I am doing wrong in this section
A queck google suggest people commonly use the FNV hash algorithm which seems like it would be easy enough to implement for |
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 change the base branch of this PR to |
FNV based hash doesn't seem much faster.
vs
|
examples/hashmap.dx
Outdated
tryGet = tryGetHashDict | ||
|
||
|
||
' all of the following error except the first |
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 comment is wrong, only the tryGet
error.
but I don't know why they do
:p tryGet eg_listdict 'a'
Type error:Ambiguous type variables: [?2]
( ()
, ( ( tmp @> ( ((k:Type)
?-> (v:Type)
?-> (Associative (ListDict Word8 Int32) k v)
?=> (ListDict Word8 Int32) -> k -> Maybe v)
, (tryGet (ListDict Word8 Int32)) )
, tmp1 @> ( ((v:Type)
?-> (Associative (ListDict Word8 Int32) Word8 v)
?=> (ListDict Word8 Int32) -> Word8 -> Maybe v)
, (tmp Word8) )
, tmp2 @> ( ((Associative (ListDict Word8 Int32) Word8 ?2)
?=> (ListDict Word8 Int32) -> Word8 -> Maybe ?2)
, (tmp1 ?2) )
, tmp3 @> (((ListDict Word8 Int32) -> Word8 -> Maybe ?2), (tmp2 _))
, tmp4 @> ((Word8 -> Maybe ?2), (tmp3 eg_listdict))
, tmp5 @> ((Maybe ?2), (tmp4 'a'))
, tmp6 @> ((Maybe ?2), tmp5)
, _ans_ @> ((Maybe ?2), tmp6) )
, [ tmp:((k:Type)
?-> (v:Type)
?-> (Associative (ListDict Word8 Int32) k v)
?=> (ListDict Word8 Int32) -> k -> Maybe v) =
tryGet (ListDict Word8 Int32)
, tmp1:((v:Type)
?-> (Associative (ListDict Word8 Int32) Word8 v)
?=> (ListDict Word8 Int32) -> Word8 -> Maybe v) = tmp Word8
, tmp2:((Associative (ListDict Word8 Int32) Word8 ?2)
?=> (ListDict Word8 Int32) -> Word8 -> Maybe ?2) = tmp1 ?2
, tmp3:((ListDict Word8 Int32) -> Word8 -> Maybe ?2) = tmp2 _
, tmp4:(Word8 -> Maybe ?2) = tmp3 eg_listdict
, tmp5:(Maybe ?2) = tmp4 'a'
, tmp6:(Maybe ?2) = tmp5
, _ans_:(Maybe ?2) = tmp6 ] ) )
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 pretty sure that this is because Dex isn't aware that the dict
parameter of Associative
actually implies the values of k
and v
. Nothing prevents you from defining weird instances such as Associative (HashDict k v) Int Float
, so it conservatively assumes that this code is ambiguous.
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.
FWIW, the same problem in Haskell is solved using the FunctionalDependencies extension, but we don't have it in Dex, and I'm not sure if we should. Our type class design is still a bit up in the air.
timing (squash me. should use %bench)
This is pretty neat I think
Closes #332
It has a List backed dictionary and a hash based dictionary
TODO
interface
/instance
stuff, not@instance
Split Hashable into seperate type classes formake Hashable use Eq, and don't make Float hashableisequal
andhash
Maybe TODO
Not TODO: