<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from text --><style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<meta content="text/html; charset=UTF-8">
<style type="text/css" style="">
<!--
p
        {margin-top:0;
        margin-bottom:0}
-->
</style>
<div dir="ltr">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:#000000; font-family:Calibri,Helvetica,sans-serif">
<p>> <span style="font-size:12pt">The current Spur VM makes x >= 1 about 1.5x faster than x >= y, because it </span><span style="font-size:12pt">has more type information available.</span></p>
<div><br>
</div>
<div><span style="font-size:12pt">Wow, this is interesting.</span><br>
</div>
<div><span style="font-size:12pt">However, I found out it is even faster to use #to:do: (4.2 ms vs. 5.19 ms). I will send this soon to the inbox.</span><br>
</div>
<div><br>
</div>
<div><span style="font-size:12pt">Just one other question before: I just discovered that we have #detect:ifNone: and also #find:ifNone: and #findBinary:ifNone:. #ifAbsent: rather appears to go with #at:, i. e. lookup operations, whereas #ifNone: goes with search
 operations. Are you still sure that we shouldn't name the thing #findFirst:ifNone:?</span></div>
<div><span style="font-size:12pt"><br>
</span></div>
<div><span style="font-size:12pt">Best,</span></div>
<div><span style="font-size:12pt">Christoph</span></div>
<p></p>
<div id="x_Signature">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:rgb(0,0,0); font-family:Calibri,Helvetica,sans-serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<div name="x_divtagdefaultwrapper" style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:; margin:0">
<div><font size="2" color="#808080"></font></div>
</div>
</div>
</div>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>Von:</b> Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> im Auftrag von Levente Uzonyi <leves@caesar.elte.hu><br>
<b>Gesendet:</b> Montag, 17. Februar 2020 15:10:10<br>
<b>An:</b> The general-purpose Squeak developers list<br>
<b>Betreff:</b> Re: [squeak-dev] The Inbox: Collections-ct.875.mcz</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">Hi Christoph,<br>
<br>
On Mon, 17 Feb 2020, Thiede, Christoph wrote:<br>
<br>
> <br>
> Hi Levente,<br>
> <br>
> <br>
> alright, I'll try to measure and optimize them again.<br>
> <br>
> <br>
> > Two things I saw and you didn't mention are block creation<br>
> <br>
> <br>
> You mean that "ifNone: [0]"? One could replace it with "ifNone: 0" to avoid duplication.<br>
<br>
That's a possible way, but there's an even better one: put the actual <br>
implementation into #findFirst:startingAt:, and let <br>
#findFirst:startingAt:ifAbsent: use it. Just like how it's done in the <br>
#indexOf:* methods.<br>
<br>
> <br>
> > and introduction of non-jittable comparison.<br>
> <br>
> What are you referring to?<br>
<br>
The current Spur VM makes x >= 1 about 1.5x faster than x >= y, because it <br>
has more type information available.<br>
<br>
Another possible optimization in #findFirst: is to store #size in a <br>
temporary instead of accessing it in each iteration.<br>
<br>
Levente<br>
<br>
> <br>
> Best,<br>
> Christoph<br>
> <br>
> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________<br>
> Von: Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> im Auftrag von Levente Uzonyi <leves@caesar.elte.hu><br>
> Gesendet: Montag, 17. Februar 2020 01:00:11<br>
> An: The general-purpose Squeak developers list<br>
> Betreff: Re: [squeak-dev] The Inbox: Collections-ct.875.mcz  <br>
> Hi Christoph,<br>
> <br>
> On Sun, 16 Feb 2020, Thiede, Christoph wrote:<br>
> <br>
> ><br>
> > Hi Levente,<br>
> ><br>
> ><br>
> > thanks for the suggestions.<br>
> ><br>
> ><br>
> > > And one more thing: These method resemble #indexOf:* methods, so I think #ifAbsent: is a better choice than #ifNone:.<br>
> ><br>
> ><br>
> > Agreed :-)<br>
> ><br>
> > > I suggest keeping the all method comments<br>
> ><br>
> > Personally, I see little value in documenting a one-liner. Documentation is useful for explaining and optimized method that does not provide the typical Smalltalk readability. Plus, they all need to be maintained ...<br>
> <br>
> If one sees #findLast: being sent somewhere, and one doesn't know what it<br>
> does, with your changes, it means looking up the implementors three times<br>
> to get to the actual implementation and comment.<br>
> <br>
> ><br>
> > > measuring the performance impact of the rewrite.<br>
> ><br>
> > What is the critical point here?<br>
> > Of course, the stack will be a little higher, but the asymptotic cost does not change. We only evaluate anotherBlock at the end instead of returning 0.<br>
> <br>
> Two things I saw and you didn't mention are block creation and<br>
> introduction of non-jittable comparison.<br>
> <br>
> ><br>
> > Please do not misunderstand me: I honor optimizing critical Smalltalk methods, but I always strive to avoid premature optimization.<br>
> <br>
> In my opinion, generic library methods like these should be optimized by<br>
> definition.<br>
> <br>
> Calling premature optimization means that you assume that if these methods<br>
> were written in a more optimal way, then their complexity and/or<br>
> legibility would be worse.<br>
> Have a look at #indexOf:*, and you'll see that's not the case.<br>
> <br>
> > Should we maybe establish to practice to store such benchmarks somewhere in the trunk so that not every willing contributor needs to write them again?<br>
> <br>
> I think methods like these don't change often enough (presumably they<br>
> never change) to justify storing benchmarks for them.<br>
> <br>
> <br>
> Levente<br>
> <br>
> ><br>
> > Best,<br>
> > Christoph<br>
> ><br>
> >________________________________________________________________________________________________________________________________________________________________________________________________________________________________<br>
> _<br>
> > Von: Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> im Auftrag von Levente Uzonyi <leves@caesar.elte.hu><br>
> > Gesendet: Sonntag, 16. Februar 2020 22:47:10<br>
> > An: The general-purpose Squeak developers list<br>
> > Betreff: Re: [squeak-dev] The Inbox: Collections-ct.875.mcz  <br>
> > And one more thing: These method resemble #indexOf:* methods, so I think<br>
> > #ifAbsent: is a better choice than #ifNone:.<br>
> ><br>
> > Levente<br>
> ><br>
> > On Sun, 16 Feb 2020, Levente Uzonyi wrote:<br>
> ><br>
> > > Hi Christoph,<br>
> > ><br>
> > > I suggest keeping the all method comments, and measuring the performance<br>
> > > impact of the rewrite.<br>
> > ><br>
> > > Levente<br>
> > ><br>
> > > On Sun, 16 Feb 2020, commits@source.squeak.org wrote:<br>
> > ><br>
> > >> A new version of Collections was added to project The Inbox:<br>
> > >> <a href="http://source.squeak.org/inbox/Collections-ct.875.mcz">http://source.squeak.org/inbox/Collections-ct.875.mcz</a><br>
> > >><br>
> > >> ==================== Summary ====================<br>
> > >><br>
> > >> Name: Collections-ct.875<br>
> > >> Author: ct<br>
> > >> Time: 16 February 2020, 3:32:23.116 pm<br>
> > >> UUID: 61ea773b-1408-c040-a712-09238ee6fe2f<br>
> > >> Ancestors: Collections-topa.873<br>
> > >><br>
> > >> Extends and realigns version of #findFirst: and #findLast:.<br>
> > >><br>
> > >> =============== Diff against Collections-topa.873 ===============<br>
> > >><br>
> > >> Item was changed:<br>
> > >>  ----- Method: SequenceableCollection>>findFirst: (in category<br>
> > > 'enumerating') -----<br>
> > >>  findFirst: aBlock<br>
> > >> -     "Return the index of my first element for which aBlock evaluates as<br>
> > > true."<br>
> > >><br>
> > >> +     ^ self findFirst: aBlock startingAt: 1!<br>
> > >> -     | index |<br>
> > >> -     index := 0.<br>
> > >> -     [(index := index + 1) <= self size] whileTrue:<br>
> > >> -             [(aBlock value: (self at: index)) ifTrue: [^index]].<br>
> > >> -     ^ 0!<br>
> > >><br>
> > >> Item was added:<br>
> > >> + ----- Method: SequenceableCollection>>findFirst:ifNone: (in category<br>
> > > 'enumerating') -----<br>
> > >> + findFirst: aBlock ifNone: anotherBlock<br>
> > >> +<br>
> > >> +     ^ self findFirst: aBlock startingAt: 1 ifNone: anotherBlock!<br>
> > >><br>
> > >> Item was added:<br>
> > >> + ----- Method: SequenceableCollection>>findFirst:startingAt: (in category<br>
> > > 'enumerating') -----<br>
> > >> + findFirst: aBlock startingAt: minIndex<br>
> > >> +<br>
> > >> +     ^ self findFirst: aBlock startingAt: minIndex ifNone: [0]!<br>
> > >><br>
> > >> Item was added:<br>
> > >> + ----- Method: SequenceableCollection>>findFirst:startingAt:ifNone: (in<br>
> > > category 'enumerating') -----<br>
> > >> + findFirst: aBlock startingAt: minIndex ifNone: anotherBlock<br>
> > >> +     "Return the index of my first element with index >= minIndex for<br>
> > > which aBlock evaluates as true. If no element is found, return the value of<br>
> > > anotherBlock."<br>
> > >> +<br>
> > >> +     | index |<br>
> > >> +     index := minIndex - 1.<br>
> > >> +     [(index := index + 1) <= self size] whileTrue:<br>
> > >> +             [(aBlock value: (self at: index)) ifTrue: [^index]].<br>
> > >> +     ^ anotherBlock value!<br>
> > >><br>
> > >> Item was changed:<br>
> > >>  ----- Method: SequenceableCollection>>findLast: (in category<br>
> > > 'enumerating') -----<br>
> > >>  findLast: aBlock<br>
> > >> -     "Return the index of my last element for which aBlock evaluates as<br>
> > > true."<br>
> > >><br>
> > >> +     ^ self findLast: aBlock startingAt: 1!<br>
> > >> -     | index |<br>
> > >> -     index := self size + 1.<br>
> > >> -     [(index := index - 1) >= 1] whileTrue:<br>
> > >> -             [(aBlock value: (self at: index)) ifTrue: [^index]].<br>
> > >> -     ^ 0!<br>
> > >><br>
> > >> Item was added:<br>
> > >> + ----- Method: SequenceableCollection>>findLast:ifNone: (in category<br>
> > > 'enumerating') -----<br>
> > >> + findLast: aBlock ifNone: anotherBlock<br>
> > >> +<br>
> > >> +     ^ self findLast: aBlock startingAt: 1 ifNone: anotherBlock!<br>
> > >><br>
> > >> Item was changed:<br>
> > >>  ----- Method: SequenceableCollection>>findLast:startingAt: (in category<br>
> > > 'enumerating') -----<br>
> > >> + findLast: aBlock startingAt: minIndex<br>
> > >> - findLast: aBlock startingAt: i<br>
> > >> -     "Return the index of my last element with index >= i for which aBlock<br>
> > > evaluates as true."<br>
> > >><br>
> > >> +     ^ self findLast: aBlock startingAt: minIndex ifNone: [0]!<br>
> > >> -     | index |<br>
> > >> -     index := self size + 1.<br>
> > >> -     [(index := index - 1) >= i] whileTrue:<br>
> > >> -             [(aBlock value: (self at: index)) ifTrue: [^index]].<br>
> > >> -     ^ 0!<br>
> > >><br>
> > >> Item was added:<br>
> > >> + ----- Method: SequenceableCollection>>findLast:startingAt:ifNone: (in<br>
> > > category 'enumerating') -----<br>
> > >> + findLast: aBlock startingAt: minIndex ifNone: anotherBlock<br>
> > >> +     "Return the index of my last element with index >= minIndex for which<br>
> > > aBlock evaluates as true.  If no element is found, return the value of<br>
> > > anotherBlock."<br>
> > >> +<br>
> > >> +     | index |<br>
> > >> +     index := self size + 1.<br>
> > >> +     [(index := index - 1) >= minIndex] whileTrue:<br>
> > >> +             [(aBlock value: (self at: index)) ifTrue: [^index]].<br>
> > >> +     ^ anotherBlock value!<br>
> > ><br>
> > ><br>
> ><br>
> ><br>
> ><br>
> <br>
></div>
</span></font>
</body>
</html>