<div dir="ltr">You're right.  I was actually dealing with an OrderedDictionary and got too comfortable seeing it through a "SequenceableCollection" lens, forgot about the hashing side and the need for growTo to calculate a goodPrime anyway.  That clears up my confusion, thanks.    :)<div><br></div><div>So, goodPrime is a trade-off between allocation and access performance.  I definitely like your optimization to favor access.</div><div><br></div><div>goodPrime is an unvaoidable cost, and your Collections-ul.867 looks like a 3X improvement (for my Dictionary example), and low risk.  Worth including in 5.3, IMO..</div><div><br></div><div>Thanks,</div><div>  Chris</div><div><div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Dec 17, 2019 at 7:39 PM Levente Uzonyi <<a href="mailto:leves@caesar.elte.hu" target="_blank">leves@caesar.elte.hu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Chris,<br>
<br>
On Tue, 17 Dec 2019, Chris Muller wrote:<br>
<br>
> Hi all,<br>
> I just noticed that attempting to optimize the creation of a Dictionary or OrderedDictionary by specifying a pre-allocated size, actually slows the system down more than not using this optimization.  In trunk, see?<br>
> <br>
> [Dictionary new] bench.        '26,300,000 per second. 38.1 nanoseconds per run. 9.21816 % GC time.'<br>
> <br>
> [Dictionary new: 4] bench.       '3,560,000 per second. 281 nanoseconds per run. 2.41952 % GC time.'<br>
> <br>
> So then I tried to debug it to see why, and I couldn't without my Tools-cmm.926 patch currently in the Inbox for review.<br>
<br>
You can't beat #new with #new: if you need to store <= 3 elements, because <br>
#new has the capacity of 5 hard-coded, while #new: has to figure out the <br>
correct capacity.<br>
If you intend to store 4 pairs in your dictionary, then it's still worth <br>
to use #new: instead of #new, because growing costs a lot more than <br>
allocating well-sized collections[1].<br>
<br>
As you found out, the performance difference between #new and #new: boils <br>
down to #goodPrimesAtLeast:. But #sizeFor:, and allocation (7 slots <br>
instead of 5) make a difference as well.<br>
<br>
I just pushed Collections-ul.867 to the inbox, which should help with <br>
your problem, but this still won't make [ Dictionary new: 4 ] as fast as [ <br>
Dictionary new ]. Why?<br>
Even though these changes make #goodPrimesAtLeast: ~8x faster for your <br>
case, #new: will still take about two times as long as #new.<br>
<br>
<br>
Levente<br>
<br>
[1]<br>
[ Dictionary new<br>
        at: 1 put: 1;<br>
        at: 2 put: 2;<br>
        at: 3 put: 3;<br>
        at: 4 put: 4 ] bench. '2,110,000 per second. 474 nanoseconds per run. 4.87805 % GC time.'.<br>
[ (Dictionary new: 4)<br>
        at: 1 put: 1;<br>
        at: 2 put: 2;<br>
        at: 3 put: 3;<br>
        at: 4 put: 4 ] bench. '3,580,000 per second. 279 nanoseconds per run. 5.19896 % GC time.'<br>
<br>
> <br>
>        Dictionary new: 4    "try to debug-it and step into"<br>
> <br>
> The whole purpose of #new: over #new is to increase the performance of allocation when the minimum size is known in advance, but we seem to have killed this goal by the cost of #goodPrimeAtLeast:.  Levente?<br>
> <br>
> Best,<br>
>   Chris<br>
> <br>
></blockquote></div>