I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
that would actually be interesting on how much you win by doing so, and if you could run this dynamically (for instance reintroduce the #class optimization if you never override it in the image)... On 2013-09-03, at 19:07, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
Well, #class slot is not really available because the trick is hardcoded in the VM as well as == trick, so no lookup in specialSelectors (specailObjectsArray at: 24) is attempted for these 2. COG also optimize some arithmetic messages, comparisons, bit ops, and all is hardcoded in the VM, so better not playing with those indices. So I tried to just replace #blockCopy: 1 with #not 0, ran some tests but saw no significative speed up. Then I tried to run Kernel tests twice in a unmodified 3.0 image [(Smalltalk allClasses select: [:e | (e category beginsWith: 'KernelTests') and: [e inheritsFrom: TestCase]]) do: [:e | e suite run]] timeToRun. 113342 114337 Then optimized the mosttly sent message during tests : IRByteCodeGenerator>>specialSelectorsArray ^ #(#+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 nil 0 #assert: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0) Recompiled all: IRBytecodeGenerator initializeSpecialSelectors. Smalltalk specialObjectsArray at: 24 put: IRBytecodeGenerator specialSelectorsArray. OpalCompiler recompileAll. Then tried the tests twice again: [(Smalltalk allClasses select: [:e | (e category beginsWith: 'KernelTests') and: [e inheritsFrom: TestCase]]) do: [:e | e suite run]] timeToRun. 84328 83974 So it seems like it's not just a space optimization but also a speed one, and I don't know why... It would be better if someone could repeat these results... Nicolas 2013/9/4 Camillo Bruni <camillobruni@gmail.com>
that would actually be interesting on how much you win by doing so, and if you could run this dynamically (for instance reintroduce the #class optimization if you never override it in the image)...
On 2013-09-03, at 19:07, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
Hmm... my timings are not reliable, I tried again with IRByteCodeGenerator>> specialSelectorsArray ^ #(#+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 nil 0 nil 0 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0) Recompiled all: IRBytecodeGenerator initializeSpecialSelectors. Smalltalk specialObjectsArray at: 24 put: IRBytecodeGenerator specialSelectorsArray. OpalCompiler recompileAll. and got a fast run 84446 too without optimizing assert: so it looks just like a space optimization. 2013/9/4 Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com>
Well, #class slot is not really available because the trick is hardcoded in the VM as well as == trick, so no lookup in specialSelectors (specailObjectsArray at: 24) is attempted for these 2. COG also optimize some arithmetic messages, comparisons, bit ops, and all is hardcoded in the VM, so better not playing with those indices.
So I tried to just replace #blockCopy: 1 with #not 0, ran some tests but saw no significative speed up.
Then I tried to run Kernel tests twice in a unmodified 3.0 image
[(Smalltalk allClasses select: [:e | (e category beginsWith: 'KernelTests') and: [e inheritsFrom: TestCase]]) do: [:e | e suite run]] timeToRun. 113342 114337
Then optimized the mosttly sent message during tests :
IRByteCodeGenerator>>specialSelectorsArray
^ #(#+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 nil 0 #assert: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0)
Recompiled all:
IRBytecodeGenerator initializeSpecialSelectors. Smalltalk specialObjectsArray at: 24 put: IRBytecodeGenerator specialSelectorsArray. OpalCompiler recompileAll.
Then tried the tests twice again:
[(Smalltalk allClasses select: [:e | (e category beginsWith: 'KernelTests') and: [e inheritsFrom: TestCase]]) do: [:e | e suite run]] timeToRun. 84328 83974
So it seems like it's not just a space optimization but also a speed one, and I don't know why... It would be better if someone could repeat these results...
Nicolas
2013/9/4 Camillo Bruni <camillobruni@gmail.com>
that would actually be interesting on how much you win by doing so, and if you could run this dynamically (for instance reintroduce the #class optimization if you never override it in the image)...
On 2013-09-03, at 19:07, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
On Tue, Sep 3, 2013 at 7:14 PM, Camillo Bruni <camillobruni@gmail.com>wrote:
that would actually be interesting on how much you win by doing so, and if you could run this dynamically (for instance reintroduce the #class optimization if you never override it in the image)...
Please don't. Sometimes this is useful for proxies....
On 2013-09-03, at 19:07, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
-- Mariano http://marianopeck.wordpress.com
On Sep 4, 2013, at 12:08 AM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
I am not sure if optimizations on that level make sense⦠Marcus
Agree, My point was to ensure there was no speedup, so it's only a space optimization (1 slot saved from literals, times 5000 senders or so per selector plus maybe a byte for the send bytecode ?). However the arithmetic ops, comparisons, bit ops, at: at:put:, == and class special selectors still have some specific speed up, especially in COG, so we cannot get rid of specialSelectors alltogether... 2013/9/4 Marcus Denker <marcus.denker@inria.fr>
On Sep 4, 2013, at 12:08 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
I am not sure if optimizations on that level make senseâ¦
Marcus
i think you can feel the difference while running interpreter. With JIT it makes little sense to have special selectors imo. On 4 September 2013 12:31, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Agree, My point was to ensure there was no speedup, so it's only a space optimization (1 slot saved from literals, times 5000 senders or so per selector plus maybe a byte for the send bytecode ?). However the arithmetic ops, comparisons, bit ops, at: at:put:, == and class special selectors still have some specific speed up, especially in COG, so we cannot get rid of specialSelectors alltogether...
2013/9/4 Marcus Denker <marcus.denker@inria.fr>
On Sep 4, 2013, at 12:08 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
I am not sure if optimizations on that level make senseâ¦
Marcus
-- Best regards, Igor Stasenko.
As I see it, there is around a hundred kBytes gain overall, maybe more in a production image full of add-on classes. Not that much nowadays, but since we cannot remove the complexity, it's still worth to select the selectors with most references. 2013/9/4 Igor Stasenko <siguctua@gmail.com>
i think you can feel the difference while running interpreter. With JIT it makes little sense to have special selectors imo.
On 4 September 2013 12:31, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Agree, My point was to ensure there was no speedup, so it's only a space optimization (1 slot saved from literals, times 5000 senders or so per selector plus maybe a byte for the send bytecode ?). However the arithmetic ops, comparisons, bit ops, at: at:put:, == and class special selectors still have some specific speed up, especially in COG, so we cannot get rid of specialSelectors alltogether...
2013/9/4 Marcus Denker <marcus.denker@inria.fr>
On Sep 4, 2013, at 12:08 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
I am not sure if optimizations on that level make senseâ¦
Marcus
-- Best regards, Igor Stasenko.
In JIT, it makes sense because there are special handling for well known special selectors (#+ #at: #< etc...). 2013/9/4 Igor Stasenko <siguctua@gmail.com>
i think you can feel the difference while running interpreter. With JIT it makes little sense to have special selectors imo.
On 4 September 2013 12:31, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Agree, My point was to ensure there was no speedup, so it's only a space optimization (1 slot saved from literals, times 5000 senders or so per selector plus maybe a byte for the send bytecode ?). However the arithmetic ops, comparisons, bit ops, at: at:put:, == and class special selectors still have some specific speed up, especially in COG, so we cannot get rid of specialSelectors alltogether...
2013/9/4 Marcus Denker <marcus.denker@inria.fr>
On Sep 4, 2013, at 12:08 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
I am not sure if optimizations on that level make senseâ¦
Marcus
-- Best regards, Igor Stasenko.
On Wed, Sep 4, 2013 at 3:35 AM, Igor Stasenko <siguctua@gmail.com> wrote:
i think you can feel the difference while running interpreter. With JIT it makes little sense to have special selectors imo.
There are two advantages. Space; special selectors encode a message send in 1 byte, instead of 1 byte for the send bytecode + 4 bytes for the literal selector. Optimization; the JIT (as does the interpreter) inlines +,-,*,/ etc for SmallInteger and then does even more inlining for
,<,>=,<=,== when they're followed by a jump.
As far as space goes, now that the system is 32-bit, and especially if it is 64-bit there is an opportunity to add 256 special selectors and use a two-byte special selector bytecode, 2 < 1 + 4. VisualWorks does this. There are problems though; over time the most statically frequent selectors can change as the library changes (e.g. blockCopy: is no longer used).
On 4 September 2013 12:31, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Agree, My point was to ensure there was no speedup, so it's only a space optimization (1 slot saved from literals, times 5000 senders or so per selector plus maybe a byte for the send bytecode ?). However the arithmetic ops, comparisons, bit ops, at: at:put:, == and class special selectors still have some specific speed up, especially in COG, so we cannot get rid of specialSelectors alltogether...
2013/9/4 Marcus Denker <marcus.denker@inria.fr>
On Sep 4, 2013, at 12:08 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
I note that #class was removed from specialSelectors (nilled entry) so as to not use the VM hack which fetches the class without sending a message. Pharo prefers the regular message send. But next to that entry, there is #blockCopy: which was formerly used for blue book BlockContext. BlockContext was removed from Pharo... So that makes two available slots for optimizing most used (sent) messages... We might choose some candidates and test on some macro benchmark if ever that really makes a difference.
I am not sure if optimizations on that level make senseâ¦
Marcus
-- Best regards, Igor Stasenko.
-- best, Eliot
participants (6)
-
Camillo Bruni -
Eliot Miranda -
Igor Stasenko -
Marcus Denker -
Mariano Martinez Peck -
Nicolas Cellier