Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

Holger Freyther
Hi,

Magritte and my TagLengthValue (TLV) both use >>#instVarNamed:/>>#instVarNamed:put: to read and write from an object. I was just running >>#bench on my SMPP library and noticed that besides Spur Pharo5 is slower than Pharo3.


I added this to PointerLayout:

>># instVarIndexFor: aString ifAbsent: aBlockClosure
        | idx |
        idx := 1.
        slotScope do: [:each |
                each isVisible ifTrue: [
                        each name = aString ifTrue: [^idx].
                        idx := idx +1]].
        ^aBlockClosure value

and modified ClassDescription/TClassDescription to use it:

"protocol: instance variables"
instVarIndexFor: instVarName ifAbsent: aBlock
        "Answer the index of the named instance variable."

        | index |
        index := self classLayout instVarIndexFor: instVarName ifAbsent: [0].
        index = 0 ifTrue:
                [^self superclass == nil
                        ifTrue: [aBlock value]
                        ifFalse: [self superclass instVarIndexFor: instVarName ifAbsent: aBlock]].
        ^self superclass == nil
                ifTrue: [index]
                ifFalse: [index + self superclass instSize]


The speed-up comes from filtering allSlots to allVisibleSlots (and creating an Array), then collecting the slot names and finally searching the name. Does it make sense to integrate such speed-ups?


cheers
        holger


Reply | Threaded
Open this post in threaded view
|

Re: Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

stepharo

> Hi,
>
> Magritte and my TagLengthValue (TLV) both use >>#instVarNamed:/>>#instVarNamed:put: to read and write from an object. I was just running >>#bench on my SMPP library and noticed that besides Spur Pharo5 is slower than Pharo3.
>
>
> I added this to PointerLayout:
>
>>> # instVarIndexFor: aString ifAbsent: aBlockClosure
> | idx |
> idx := 1.
> slotScope do: [:each |
> each isVisible ifTrue: [
> each name = aString ifTrue: [^idx].
> idx := idx +1]].
> ^aBlockClosure value
>
> and modified ClassDescription/TClassDescription to use it:
>
> "protocol: instance variables"
> instVarIndexFor: instVarName ifAbsent: aBlock
> "Answer the index of the named instance variable."
>
> | index |
> index := self classLayout instVarIndexFor: instVarName ifAbsent: [0].
> index = 0 ifTrue:
> [^self superclass == nil
> ifTrue: [aBlock value]
> ifFalse: [self superclass instVarIndexFor: instVarName ifAbsent: aBlock]].
> ^self superclass == nil
> ifTrue: [index]
> ifFalse: [index + self superclass instSize]
>
>
> The speed-up comes from filtering allSlots to allVisibleSlots (and creating an Array), then collecting the slot names and finally searching the name. Does it make sense to integrate such speed-ups?

Yes!!!!!!!!!!!!!!!!!!!!!!
  if you can just improve a bit the method comments it would be really
great!

>
>
> cheers
> holger
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

vonbecmann
In reply to this post by Holger Freyther
cheap hack.

if you replace this line

index := self classLayout instVarIndexFor: instVarName ifAbsent: [0].

with

index := self classLayout instVarIndexFor: instVarName ifAbsent: 0.

in instVarIndexFor: instVarName ifAbsent: aBlock

it will be faster because it won't create a closure, but no one will approve that use. to cheap :)



On Wed, Sep 28, 2016 at 6:41 PM, Holger Freyther <[hidden email]> wrote:
Hi,

Magritte and my TagLengthValue (TLV) both use >>#instVarNamed:/>>#instVarNamed:put: to read and write from an object. I was just running >>#bench on my SMPP library and noticed that besides Spur Pharo5 is slower than Pharo3.


I added this to PointerLayout:

>># instVarIndexFor: aString ifAbsent: aBlockClosure
        | idx |
        idx := 1.
        slotScope do: [:each |
                each isVisible ifTrue: [
                        each name = aString ifTrue: [^idx].
                        idx := idx +1]].
        ^aBlockClosure value

and modified ClassDescription/TClassDescription to use it:

"protocol: instance variables"
instVarIndexFor: instVarName ifAbsent: aBlock
        "Answer the index of the named instance variable."

        | index |
        index := self classLayout instVarIndexFor: instVarName ifAbsent: [0].
        index = 0 ifTrue:
                [^self superclass == nil
                        ifTrue: [aBlock value]
                        ifFalse: [self superclass instVarIndexFor: instVarName ifAbsent: aBlock]].
        ^self superclass == nil
                ifTrue: [index]
                ifFalse: [index + self superclass instSize]


The speed-up comes from filtering allSlots to allVisibleSlots (and creating an Array), then collecting the slot names and finally searching the name. Does it make sense to integrate such speed-ups?


cheers
        holger





--
Bernardo E.C.

Sent from a cheap desktop computer in South America.
Reply | Threaded
Open this post in threaded view
|

Re: Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

Marcus Denker-4
In reply to this post by Holger Freyther

> On 28 Sep 2016, at 23:41, Holger Freyther <[hidden email]> wrote:
>
> Hi,
>
> Magritte and my TagLengthValue (TLV) both use >>#instVarNamed:/>>#instVarNamed:put: to read and write from an object. I was just running >>#bench on my SMPP library and noticed that besides Spur Pharo5 is slower than Pharo3.
>
>
> I added this to PointerLayout:
>
>>> # instVarIndexFor: aString ifAbsent: aBlockClosure
> | idx |
> idx := 1.
> slotScope do: [:each |
> each isVisible ifTrue: [
> each name = aString ifTrue: [^idx].
> idx := idx +1]].
> ^aBlockClosure value
>
> and modified ClassDescription/TClassDescription to use it:
>
> "protocol: instance variables"
> instVarIndexFor: instVarName ifAbsent: aBlock
> "Answer the index of the named instance variable."
>
> | index |
> index := self classLayout instVarIndexFor: instVarName ifAbsent: [0].
> index = 0 ifTrue:
> [^self superclass == nil
> ifTrue: [aBlock value]
> ifFalse: [self superclass instVarIndexFor: instVarName ifAbsent: aBlock]].
> ^self superclass == nil
> ifTrue: [index]
> ifFalse: [index + self superclass instSize]
>
>
> The speed-up comes from filtering allSlots to allVisibleSlots (and creating an Array), then collecting the slot names and finally searching the name. Does it make sense to integrate such speed-ups?
>
>

Yes! I will add it.

        Marcus


Reply | Threaded
Open this post in threaded view
|

Re: Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

Marcus Denker-4

On 29 Sep 2016, at 10:08, Marcus Denker <[hidden email]> wrote:


On 28 Sep 2016, at 23:41, Holger Freyther <[hidden email]> wrote:

Hi,

Magritte and my TagLengthValue (TLV) both use >>#instVarNamed:/>>#instVarNamed:put: to read and write from an object. I was just running >>#bench on my SMPP library and noticed that besides Spur Pharo5 is slower than Pharo3.


Yes! I will add it.


Slice committed:

https://pharo.fogbugz.com/f/cases/19155/speedup-instVarNamed

Marcus


Reply | Threaded
Open this post in threaded view
|

Re: Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

Holger Freyther

> On 29 Sep 2016, at 10:25, Marcus Denker <[hidden email]> wrote:
>
>

>
> Slice committed:
>
> https://pharo.fogbugz.com/f/cases/19155/speedup-instVarNamed
>
> Marcus


that was quick!

I had locally modified to use 1 to: specLayout size do: [] and then use specLayout at: directly. It seemed to make a small difference as well

So I was "lucky" to pick PointerLayout as class to put the method in? classLayout will always be an instance of PointerLayout (or its subclasses)?

thank you
        holger


PS: It luckily speeds up instVarNamed:put: as well :)
Reply | Threaded
Open this post in threaded view
|

Re: Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

Denis Kudriashov
In reply to this post by Holger Freyther
Cool.

What the percentage of speedup?

2016-09-28 23:41 GMT+02:00 Holger Freyther <[hidden email]>:
Hi,

Magritte and my TagLengthValue (TLV) both use >>#instVarNamed:/>>#instVarNamed:put: to read and write from an object. I was just running >>#bench on my SMPP library and noticed that besides Spur Pharo5 is slower than Pharo3.


I added this to PointerLayout:

>># instVarIndexFor: aString ifAbsent: aBlockClosure
        | idx |
        idx := 1.
        slotScope do: [:each |
                each isVisible ifTrue: [
                        each name = aString ifTrue: [^idx].
                        idx := idx +1]].
        ^aBlockClosure value

and modified ClassDescription/TClassDescription to use it:

"protocol: instance variables"
instVarIndexFor: instVarName ifAbsent: aBlock
        "Answer the index of the named instance variable."

        | index |
        index := self classLayout instVarIndexFor: instVarName ifAbsent: [0].
        index = 0 ifTrue:
                [^self superclass == nil
                        ifTrue: [aBlock value]
                        ifFalse: [self superclass instVarIndexFor: instVarName ifAbsent: aBlock]].
        ^self superclass == nil
                ifTrue: [index]
                ifFalse: [index + self superclass instSize]


The speed-up comes from filtering allSlots to allVisibleSlots (and creating an Array), then collecting the slot names and finally searching the name. Does it make sense to integrate such speed-ups?


cheers
        holger



Reply | Threaded
Open this post in threaded view
|

Re: Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

Holger Freyther

> On 29 Sep 2016, at 12:28, Denis Kudriashov <[hidden email]> wrote:
>
> Cool.
>
> What the percentage of speedup?

Random micro benchmark...

| m |
m := Morph new.
[ | var |
        var := m instVarNamed: #submorphs
] bench

From: 983,066 per second
To: 1,302,098 per second



Reply | Threaded
Open this post in threaded view
|

Re: Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

Tudor Girba-2
Not bad! This should have a significant impact when creating Pharo objects out of external data.

Cheers,
Doru


> On Sep 29, 2016, at 2:04 PM, Holger Freyther <[hidden email]> wrote:
>
>
>> On 29 Sep 2016, at 12:28, Denis Kudriashov <[hidden email]> wrote:
>>
>> Cool.
>>
>> What the percentage of speedup?
>
> Random micro benchmark...
>
> | m |
> m := Morph new.
> [ | var |
> var := m instVarNamed: #submorphs
> ] bench
>
> From: 983,066 per second
> To: 1,302,098 per second
>
>
>

--
www.tudorgirba.com
www.feenk.com

"Next time you see your life passing by, say 'hi' and get to know her."





Reply | Threaded
Open this post in threaded view
|

Re: Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?

Marcus Denker-4
In reply to this post by Holger Freyther


On Thu, Sep 29, 2016 at 10:34 AM, Holger Freyther <[hidden email]> wrote:

> On 29 Sep 2016, at 10:25, Marcus Denker <[hidden email]> wrote:
>
>

>
> Slice committed:
>
> https://pharo.fogbugz.com/f/cases/19155/speedup-instVarNamed
>
>       Marcus


that was quick!

I had locally modified to use 1 to: specLayout size do: [] and then use specLayout at: directly. It seemed to make a small difference as well

So I was "lucky" to pick PointerLayout as class to put the method in? classLayout will always be an instance of PointerLayout (or its subclasses)?

For all classes with ivars, yes. But we need to add a method to the superclass, too (which does nothing).

  I will commit another iteration.