Speeding-up >>#instVarNamed: in Pharo-5.0 and beyond?
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
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
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 <holger@freyther.de> 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.
On 28 Sep 2016, at 23:41, Holger Freyther <holger@freyther.de> 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
On 29 Sep 2016, at 10:08, Marcus Denker <marcus.denker@inria.fr> wrote:
On 28 Sep 2016, at 23:41, Holger Freyther <holger@freyther.de> 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 <https://pharo.fogbugz.com/f/cases/19155/speedup-instVarNamed> Marcus
On 29 Sep 2016, at 10:25, Marcus Denker <marcus.denker@inria.fr> 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 :)
On Thu, Sep 29, 2016 at 10:34 AM, Holger Freyther <holger@freyther.de> wrote:
On 29 Sep 2016, at 10:25, Marcus Denker <marcus.denker@inria.fr> 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. -- Marcus Denker -- denker@acm.org http://www.marcusdenker.de
Cool. What the percentage of speedup? 2016-09-28 23:41 GMT+02:00 Holger Freyther <holger@freyther.de>:
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
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 <holger@freyther.de> wrote:
On 29 Sep 2016, at 12:28, Denis Kudriashov <dionisiydk@gmail.com> 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."
participants (6)
-
Bernardo Ezequiel Contreras -
Denis Kudriashov -
Holger Freyther -
Marcus Denker -
stepharo -
Tudor Girba