<div dir="auto">Hi Chris,<div dir="auto">For such small size, did u try using SmallDictionary? (see in RB)</div><div dir="auto"><br></div><div dir="auto">It avoids hash and just iterate thru keys with = until hit or exhausting the tally.</div><div dir="auto"><br></div><div dir="auto">It also avoid creating Association, maintaining keys and values in 2 arrays.</div><div dir="auto"><br></div><div dir="auto">It thus has no extra room requirement.</div><div dir="auto">It seems a perfect fit for your requirements.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le sam. 25 janv. 2020 à 01:47, Chris Muller <<a href="mailto:ma.chris.m@gmail.com">ma.chris.m@gmail.com</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Hi Levente,</div><div dir="ltr"><br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">>       > That's better, but it still has that same fundamental problem.  Every time a developer makes a HashedCollection of a known-at-runtime size (e.g., in a variable), they're forced to choose between execution performance pain or code pain.<br>
>       ><br>
>       >     {<br>
>       >    '[ Dictionary new ]'->'100% of baseline rate, 27,600,000 per second. 36.2 nanoseconds per run. 11.33547 % GC time.'<br>
>       ><br>
>       >     "performance pain?"<br>
>       >     '[ Dictionary new: 1 ]'->'60% of baseline rate, 16,600,000 per second. 60.1 nanoseconds per run. 5.61888 % GC time.'<br>
>       >     '[ Dictionary new: 2 ]'->'61% of baseline rate, 16,900,000 per second. 59.2 nanoseconds per run. 5.67886 % GC time.'<br>
>       >     '[ Dictionary new: 3 ]'->'59% of baseline rate, 16,300,000 per second. 61.5 nanoseconds per run. 6.77864 % GC time.'<br>
><br>
>       Even if there's a performance overhead, you use less memory.<br>
> <br>
> <br>
> But #new: is about optimization along *both* of those dimensions.  Imagine how complicated a "manpage" for #new: would have to be if it weren't.  #new: must _never_ perform significantly worse than #new (for sizes <= the default), because it would either trick or force developers into writing less-performant<br>
> code, or into acknowledging Squeak's internal Dictionary implementation in their own code.  It feels like an API-design bug.<br>
<br>
It was okay for quite a long time. :)<br></blockquote><div><br></div><div>... until this proposal which changed the smallest internal array size from 5 to 3 and introduced the above anomaly.  I assume you made that change because you felt something else <i>wasn't</i> okay (to which I agree!).</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
>  <br>
>        >     "into #sizeFor:"<br>
><br>
>       >     '[ Dictionary new: 4 ]'->'57% of baseline rate, 15,800,000 per second. 63.5 nanoseconds per run. 7.87685 % GC time.'<br>
><br>
>       Starting from 4, you also save time by avoiding growing, which is<br>
>       more significant than what you "lose" during instance creation.<br>
> <br>
> <br>
> Except my Dictionary is never going to grow.<br>
<br>
So, we actually say the same thing.<br></blockquote><div><br></div><div>Did we?  You were arguing about saving time with growing, which I can never gain.  I only lose during instance creation...</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">> In case it helps bring clarity, my scenario is the GraphQL server.  As a Request comes in, the server will know, depending on the type, how many named arguments to expect (for most "normal" schema's, 0 to 4, but it can define any number it wants).  So it creates right sized Dictionary to hold them all, and will<br>
> never grow beyond that.  I simply don't want the server to have to do extra work when **vast majority** of requests will have fewer than 4 arguments.<br>
><br>
>       We could get rid of the anomaly by changing #new to ^self new: 3.<br>
> <br>
> <br>
> Yes, I'd be fine with that solution, too!   For me, it's only about violation of #new:'s contract.<br>
<br>
I don't see any broken contract here. It may be surprising to see <br>
somewhat worse performance with #new: than with #new (25 nanoseconds per <br>
instance according to your measurements), </blockquote><div><br></div><div>a 40% hit...</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">but both of those methods do <br>
what they should. Just because there was an easy optimization applied to <br>
#new, nothing was broken IMHO.<br></blockquote><div><br></div><div>... for using #new: that's <i style="font-weight:bold">supposed</i> to be for optimization!</div><div><br></div><div>So if you were in my shoes (which, if this goes to trunk as-is eventually you will be!), would you take a 40% hit in performance-critical code needing to instantiate a Dictionary with:</div><div><br></div><div>    Dictionary new: runtimeSize</div><div><br></div><div>Or, actually violate encapsulation to preserve performance?</div><div><br></div><div>   sz>3 ifTrue: [Dictionary new: sz] ifFalse: [Dictionary new]</div><div><br></div><div>?</div><div><br></div><div>My past observations have been that you like and appreciate the most-efficient performing code, so I'm truly curious!</div><div><br></div><div>Best Regards.</div><div>  Chris</div></div></div>
<br>
</blockquote></div>