[Vm-dev] Primitive 60 vs methods with more than one argument
David T. Lewis
lewis at mail.msen.com
Sun Oct 20 00:58:07 UTC 2013
On Sat, Oct 19, 2013 at 10:53:40PM +0200, Levente Uzonyi wrote:
>
> Hi,
>
> the code of primitive 60 seems to be assuming that the method has exactly
> one argument, ignoring the actual number of arguments. This seems to be an
> unnecessary restriction, which makes it cumbersome/impossible to use it in
> methods which have more arguments, like #at:ifAbsent:.
>
> Since the primitive uses two objects from the top of the stack, it's
> possible to write a hackish method to see the potential benefits:
>
> ifAbsent: aBlock receiver: receiver at: index
>
> <primitive: 60>
> ^aBlock value
>
> The primitive will treat the variable receiver as the receiver, and index
> as the index. The real receiver is not used at all.
>
> This method performs 37% better than #at:ifAbsent for the case where
> the index is valid.
>
> Does it have any benefits not taking the actual number of arguments into
> account in this primitive?
>
> Cheers,
> Levente
I tried a rather casual benchmark. In the VM, I changed from this:
commonAt: stringy
"This code is called if the receiver responds primitively to at:.
If this is so, it will be installed in the atCache so that subsequent calls of at:
or next may be handled immediately in bytecode primitive routines."
| index rcvr atIx result |
index := self positive32BitValueOf: (self stackTop). "Sets primFailCode"
rcvr := self stackValue: 1.
To this:
commonAt: stringy
"This code is called if the receiver responds primitively to at:.
If this is so, it will be installed in the atCache so that subsequent calls of at:
or next may be handled immediately in bytecode primitive routines."
| index rcvr atIx result |
index := self positive32BitValueOf: (self stackValue: argumentCount - 1). "Sets primFailCode"
rcvr := self stackValue: argumentCount.
Then I ran the following test with each VM:
(1 to: 25) collect: [:foo |
size := 100000000.
bigArray := Array new: size.
1 to: size do: [:i | bigArray at: i put: i].
Smalltalk garbageCollect.
Time millisecondsToRun: [1 to: size do: [:i | bigArray at: i]]].
I ended up with less than 1% performance difference between the two VMs
for the common case of #at: access to an array.
This was not a very careful test, but it suggests that your idea could
be used to improve at:ifAbsent: performance without causing significant
performance problems elsewhere.
Dave
More information about the Vm-dev
mailing list