[Pharo-project] Preallocation behavior

Andres Valloud avalloud at smalltalk.comcastbiz.net
Thu Apr 28 09:30:51 CEST 2011


As a side comment, I do not know if an atAllPut: method I wrote back in 
about 2000 or so is still in the image... but if it is not, keep in mind 
that you can use something like replaceFrom:to:with:startingAt: using 
the receiver as the source of data, duplicating the amount of data 
copied each time.  Back then, if you had to write the same object more 
than 26 or so times, it was faster to use the duplicating "block copy" 
method.  The key is to avoid multiple primitive calls (which have 
expensive overhead compared to what is actually done), and replace them 
with a single primitive call that does a bunch of writes.  With the 
duplication method, you could get away with doing 9000 writes in no more 
than 15 primitive calls.  I wrote about this in much more detail in the 
Fundamentals volume 2 book.

On 4/27/11 23:35 , jannik.laval wrote:
> Hi all,
>
> I am playing with MessageTally, and I have a strange result with
> prealocation.
> Here is my example. I am working on a PharoCore1.3, with a VM4.2.5
>
> First of all, I spy this source code:
> ====
> MessageTally spyOn:
> [ 500 timesRepeat: [
> | str |
> *str := ''*.
> 9000 timesRepeat: [ str := str, 'A' ]]].
> ====
>
> The result appears after *24 961 ms*.
> An optimization is to use a Stream. Here is my source code:
> ===
> MessageTally spyOn:
> [ 500 timesRepeat: [
> | str |
> *str := WriteStream on: (String new)*.
> 9000 timesRepeat: [ str nextPut: $A ]]].
> ===
>
> The result appears after *812 ms*, which is a large improvement.
> Now, we could optimize again using the preallocation. Here is my source
> code:
>
> ====
> MessageTally spyOn:
> [ 500 timesRepeat: [
> | str |
> *str := WriteStream on: (String new: 10000)*.
> 9000 timesRepeat: [ str nextPutAll: 'A' ]]].
> ====
>
> And the result is strange: it makes 2 times slower to display the result.
> The result appears after 1656 ms.
>
> Here is the spy result:
> ===
> - 1656 tallies, 1656 msec.
>
> **Tree**
> --------------------------------
> Process: (40s) 464519168: nil
> --------------------------------
> 
> **Leaves**
> *22.9% {380ms} UndefinedObject>>DoIt*
> 22.5% {373ms} SmallInteger(Integer)>>timesRepeat:
> 22.2% {368ms} WriteStream>>nextPutAll:
> ===
>
> There is the call of UndefinedObject>>DoIt which is added and takes time.
> Does anyone know what is done during the preallocation ?
> Why is it slower than non-preallocation ?
>
> Thanks for your answers.
> Jannik



More information about the Pharo-project mailing list