<div dir="ltr">Hi Andres,<div><br></div><div>ByteArray currently doesn&#39;t have a primitive that handles any part of getting bytes from the ByteArray and forming them into an integer.  If it did have one, I would be happy to alter the code around that.</div><div><br></div><div>The long drawn out method is 4x faster for small (SmallInteger) results, and 25% faster for LargeInteger results (those that excercise all 8 bytes).  This because it does at most 2 LargeInteger bitShifts, and as little as no LargeInteger bitShifts.  The &#39;macro&#39; version does a minimum of 1 LargeInteger bitShifts, and up to 3 of them.</div><div><br></div><div>For BigEndian platforms, speed may be important; in any case, it is nice.</div><div><br></div><div>You are probably aware, but the current Squeak has does not have #unsignedLong64At:bigEndian: in the image at all - that diff was from my first attempt.</div><div><br></div><div>-cbc</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Aug 31, 2015 at 7:39 PM, Andres Valloud <span dir="ltr">&lt;<a href="mailto:avalloud@smalltalk.comcastbiz.net" target="_blank">avalloud@smalltalk.comcastbiz.net</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
Interesting about the fading relevancy of big endian platforms.  Just in case the point was lost, I meant the macro-style approach in contrast with this (from Squeak-dev):<br>
<br>
=============== Diff against Collections-cbc.650 ===============<br>
<br>
Item was changed:<br>
  ----- Method: ByteArray&gt;&gt;unsignedLong64At:bigEndian: (in category &#39;platform independent access&#39;) -----<br>
  unsignedLong64At: index bigEndian: aBool<br>
+       &quot;Avoid as much largeInteger as we can&quot;<br>
+       | b0 b2 b3 b5 b6 w n2 n3 |<br>
+<br>
+       aBool ifFalse: [<br>
+               w := self at: index.<br>
+               b6 := self at: index+1.<br>
+               b5 := self at: index+2.<br>
+               n2 := self at: index+3.<br>
+               b3 := self at: index+4.<br>
+               b2 := self at: index+5.<br>
+               n3 := self at: index+6.<br>
+               b0 := self at: index+7.<br>
+       ] ifTrue: [<br>
+               b0 := self at: index.<br>
+               n3 := self at: index+1.<br>
+               b2 := self at: index+2.<br>
+               b3 := self at: index+3.<br>
+               n2 := self at: index+4.<br>
+               b5 := self at: index+5.<br>
+               b6 := self at: index+6.<br>
+               w := self at: index+7.<br>
+               ].<br>
+<br>
+       &quot;Minimize LargeInteger arithmetic&quot;<br>
+       b6 = 0 ifFalse:[w := (b6 bitShift: 8) + w].<br>
+       b5 = 0 ifFalse:[w := (b5 bitShift: 16) + w].<br>
+       <br>
+       b3 = 0 ifFalse:[n2 := (b3 bitShift: 8) + n2].<br>
+       b2 = 0 ifFalse:[n2 := (b2 bitShift: 16) + n2].<br>
+       n2 == 0 ifFalse: [w := (n2 bitShift: 24) + w].<br>
+<br>
+       b0 = 0 ifFalse:[n3 := (b0 bitShift: 8) + n3].<br>
+       n3 == 0 ifFalse: [w := (n3 bitShift: 48) + w].<br>
+<br>
+       ^w!<br>
-       | n1 n2 |<br>
-       aBool<br>
-               ifTrue: [<br>
-                       n2 := self unsignedLongAt: index  bigEndian: true.<br>
-                       n1 := self unsignedLongAt: index+4  bigEndian: true.<br>
-                       ]<br>
-               ifFalse: [<br>
-                       n1 := self unsignedLongAt: index bigEndian: false.<br>
-                       n2 := self unsignedLongAt: index+4 bigEndian: false.<br>
-                       ].<br>
-       ^(n2 bitShift: 32) + n1!<br>
<br>
<br>
I&#39;d rather have that pushed down enough so that the compiler intrinsic becomes visible.  And at that point, all that code is reduced to a single instruction.<span class="HOEnZb"><font color="#888888"><br>
<br>
Andres.</font></span><div><div class="h5"><br>
<br>
<br>
On 8/31/15 19:12 , Eliot Miranda wrote:<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
Hi Andres,<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On Aug 31, 2015, at 5:52 PM, Andres Valloud &lt;<a href="mailto:avalloud@smalltalk.comcastbiz.net" target="_blank">avalloud@smalltalk.comcastbiz.net</a>&gt; wrote:<br>
<br>
FWIW... IMO it&#39;s better to enable access to the relevant compiler intrinsic with platform specific macros, rather than implementing instructions such as Intel&#39;s BSWAP or MOVBE by hand.  In HPS, isolating endianness concerns from the large integer arithmetic primitives with such macros enabled 25-40% faster performance on big endian platforms. Just as importantly, the intrinsic approach takes significantly less code to implement.<br>
</blockquote>
<br>
Makes sense, and the performance increases are impressive.  The only issue I have is that the Cog JIT (which would have the easiest time generating those intrinsics) currently runs only in little-endianness platforms and I seriously doubt it will run in a big endianness platform in the next five years.  PowerPC is the only possibility I see.  Yes, ARM is biendian but all the popular applications I know of are little endian.<br>
<br>
VW&#39;s a different beast; significant big endian legacy.<br>
<br>
But what you say about isolating makes perfect sense.  Thanks<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On 8/31/15 10:25 , Eliot Miranda wrote:<br>
Hi Chrises,<br>
<br>
     my vote would be to write these as 12 numbered primitives, (2,4 &amp; 8<br>
bytes) * (at: &amp; at:put:) * (big &amp; little endian) because they can be<br>
performance critical and implementing them like this means the maximum<br>
efficiency in both 32-bit and 64-bit Spur, plus the possibility of the<br>
JIT implementing the primitives.<br>
<br>
On Sun, Aug 30, 2015 at 10:01 PM, Chris Cunningham<br>
&lt;<a href="mailto:cunningham.cb@gmail.com" target="_blank">cunningham.cb@gmail.com</a> &lt;mailto:<a href="mailto:cunningham.cb@gmail.com" target="_blank">cunningham.cb@gmail.com</a>&gt;&gt; wrote:<br>
<br>
    Hi Chris,<br>
<br>
    I&#39;m all for having the fastest that in the image that works.  If you<br>
    could make your version handle endianess, then I&#39;m all for including<br>
    it (at least in the 3 variants that are faster).  My first use for<br>
    this (interface for KAFKA) apparently requires bigEndianess, so I<br>
    really want that supported.<br>
<br>
    It might be best to keep my naming, though - it follows the name<br>
    pattern that is already in the class.  Or will yours also support 128?<br>
<br>
    -cbc<br>
<br>
    On Sun, Aug 30, 2015 at 2:38 PM, Chris Muller &lt;<a href="mailto:asqueaker@gmail.com" target="_blank">asqueaker@gmail.com</a><br>
    &lt;mailto:<a href="mailto:asqueaker@gmail.com" target="_blank">asqueaker@gmail.com</a>&gt;&gt; wrote:<br>
<br>
        Hi Chris, I think these methods belong in the image with the fastest<br>
        implementation we can do.<br>
<br>
        I implemented 64-bit unsigned access for Ma Serializer back in 2005.<br>
        I modeled my implementation after Andreas&#39; original approach which<br>
        tries to avoid LI arithmetic.  I was curious whether your<br>
        implementations would be faster, because if they are then it could<br>
        benefit Magma.  After loading &quot;Ma Serializer&quot; 1.5 (or head) into a<br>
        trunk image, I used the following script to take comparison<br>
        measurements:<br>
<br>
        | smallN largeN maBa cbBa |  smallN := ((2 raisedTo: 13) to: (2<br>
        raisedTo: 14)) atRandom.<br>
        largeN := ((2 raisedTo: 63) to: (2 raisedTo: 64)) atRandom.<br>
        maBa := ByteArray new: 8.<br>
        cbBa := ByteArray new: 8.<br>
        maBa maUint: 64 at: 0 put: largeN.<br>
        cbBa unsignedLong64At: 1 put: largeN bigEndian: false.<br>
        self assert: (cbBa maUnsigned64At: 1) = (maBa unsignedLong64At: 1<br>
        bigEndian: false).<br>
        { &#39;cbc smallN write&#39; -&gt; [ cbBa unsignedLong64At: 1 put: smallN<br>
        bigEndian: false] bench.<br>
        &#39;ma smallN write&#39; -&gt; [cbBa maUint: 64 at: 0 put: smallN ] bench.<br>
        &#39;cbc smallN access&#39; -&gt; [ cbBa unsignedLong64At: 1 bigEndian:<br>
        false. ] bench.<br>
        &#39;ma smallN access&#39; -&gt; [ cbBa maUnsigned64At: 1] bench.<br>
        &#39;cbc largeN write&#39; -&gt; [ cbBa unsignedLong64At: 1 put: largeN<br>
        bigEndian: false] bench.<br>
        &#39;ma largeN write&#39; -&gt; [cbBa maUint: 64 at: 0 put: largeN ] bench.<br>
        &#39;cbc largeN access&#39; -&gt; [ cbBa unsignedLong64At: 1 bigEndian:<br>
        false ] bench.<br>
        &#39;ma largeN access&#39; -&gt; [ cbBa maUnsigned64At: 1] bench.<br>
          }<br>
<br>
        Here are the results:<br>
<br>
        &#39;cbc smallN write&#39;-&gt;&#39;3,110,000 per second.  322 nanoseconds per<br>
        run.&#39; .<br>
        &#39;ma smallN write&#39;-&gt;&#39;4,770,000 per second.  210 nanoseconds per<br>
        run.&#39; .<br>
        &#39;cbc smallN access&#39;-&gt;&#39;4,300,000 per second.  233 nanoseconds per<br>
        run.&#39; .<br>
        &#39;ma smallN access&#39;-&gt;&#39;16,400,000 per second.  60.9 nanoseconds<br>
        per run.&#39; .<br>
        &#39;cbc largeN write&#39;-&gt;&#39;907,000 per second.  1.1 microseconds per<br>
        run.&#39; .<br>
        &#39;ma largeN write&#39;-&gt;&#39;6,620,000 per second.  151 nanoseconds per<br>
        run.&#39; .<br>
        &#39;cbc largeN access&#39;-&gt;&#39;1,900,000 per second.  527 nanoseconds per<br>
        run.&#39; .<br>
        &#39;ma largeN access&#39;-&gt;&#39;1,020,000 per second.  982 nanoseconds per<br>
        run.&#39;<br>
<br>
        It looks like your 64-bit access is 86% faster for accessing the<br>
        high-end of the 64-bit range, but slower in the other 3 metrics.<br>
        Noticeably, it was only 14% as fast for writing the high-end of the<br>
        64-bit range, and similarly as much slower for small-number access..<br>
<br>
<br>
        On Fri, Aug 28, 2015 at 6:01 PM, Chris Cunningham<br>
        &lt;<a href="mailto:cunningham.cb@gmail.com" target="_blank">cunningham.cb@gmail.com</a> &lt;mailto:<a href="mailto:cunningham.cb@gmail.com" target="_blank">cunningham.cb@gmail.com</a>&gt;&gt; wrote:<br>
         &gt; Hi.<br>
         &gt;<br>
         &gt; I&#39;ve committed a change to the inbox with changes to allow<br>
        getting/putting<br>
         &gt; 64bit values to ByteArrays (similar to 32 and 16 bit<br>
        accessors).  Could this<br>
         &gt; be added to trunk?<br>
         &gt;<br>
         &gt; Also, first time I used the selective commit function - very<br>
        nice!  the<br>
         &gt; changes I didn&#39;t want committed didn&#39;t, in fact, get<br>
        commited.  Just the<br>
         &gt; desirable bits!<br>
         &gt;<br>
         &gt; -cbc<br>
         &gt;<br>
         &gt;<br>
         &gt;<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
--<br>
_,,,^..^,,,_<br>
best, Eliot<br>
<br>
<br>
<br>
</blockquote></blockquote></div></div>
.<br>
<br>
</blockquote>
</blockquote></div><br></div>