MNU for ifNil: to preserve quick returns? :-)

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

MNU for ifNil: to preserve quick returns? :-)

marcel.taeumel
Hi all!

I can choose to initialize an instVar eagerly in #initialize or lazily in its accessor via #ifNil:. Yet, the latter requires me to change that accessor to something not being a quick return.

Could there be a simple way to initialize an instVar on its first read access? Like a #notYetInitialized: callback to the instVar-holding receiver. Instead, we get an MNU on UndefiniedObject ... 

(Why? Performance reasons for a little project of mine.)

Best,
Marcel


Reply | Threaded
Open this post in threaded view
|

Re: MNU for ifNil: to preserve quick returns? :-)

Jakob Reschke-2
Hi Marcel,

Might be cool if the JIT or Scorch emitted code that is equivalent to
a quick return, but with a low-level nil-guard in place. Like a
quick-return-if-not-nil primitive code.

Is eager initialization out of the question for you?

If all your instVars were initialized on the first read of one of
them, you could also change the class of the object after the lazy
initialization, and the new class would have quick accessors. For
added fanciness, you could auto-generate the "optimized" class and
such accessors in both classes. Though I am totally not sure whether
it is worth the effort or improves the performance at all (since the
call sites are then polymorphic).

notYetInitialized: sounds strange to me, since you could send the
getter in one place and actually use the answer in a totally different
place (where your MNU happens). You could eager-initialize and return
some special case proxy instead of nil that is bound to the original
receiver and takes care of the lazy initialization when called.

Kind regards,
Jakob

Am Di., 21. Juli 2020 um 10:36 Uhr schrieb Marcel Taeumel
<[hidden email]>:

>
> Hi all!
>
> I can choose to initialize an instVar eagerly in #initialize or lazily in its accessor via #ifNil:. Yet, the latter requires me to change that accessor to something not being a quick return.
>
> Could there be a simple way to initialize an instVar on its first read access? Like a #notYetInitialized: callback to the instVar-holding receiver. Instead, we get an MNU on UndefiniedObject ...
>
> (Why? Performance reasons for a little project of mine.)
>
> Best,
> Marcel
>

Reply | Threaded
Open this post in threaded view
|

Re: MNU for ifNil: to preserve quick returns? :-)

marcel.taeumel
Is eager initialization out of the question for you?

Not quite. But saving 400 000 extra objects where each may have 5 to 10 instVars ... could be worthwhile if those are not used at all. I suppose that all instVars being "nil" is not optimized in the VM?

Best,
Marcel

Am 21.07.2020 12:07:44 schrieb Jakob Reschke <[hidden email]>:

Hi Marcel,

Might be cool if the JIT or Scorch emitted code that is equivalent to
a quick return, but with a low-level nil-guard in place. Like a
quick-return-if-not-nil primitive code.

Is eager initialization out of the question for you?

If all your instVars were initialized on the first read of one of
them, you could also change the class of the object after the lazy
initialization, and the new class would have quick accessors. For
added fanciness, you could auto-generate the "optimized" class and
such accessors in both classes. Though I am totally not sure whether
it is worth the effort or improves the performance at all (since the
call sites are then polymorphic).

notYetInitialized: sounds strange to me, since you could send the
getter in one place and actually use the answer in a totally different
place (where your MNU happens). You could eager-initialize and return
some special case proxy instead of nil that is bound to the original
receiver and takes care of the lazy initialization when called.

Kind regards,
Jakob

Am Di., 21. Juli 2020 um 10:36 Uhr schrieb Marcel Taeumel
:

>
> Hi all!
>
> I can choose to initialize an instVar eagerly in #initialize or lazily in its accessor via #ifNil:. Yet, the latter requires me to change that accessor to something not being a quick return.
>
> Could there be a simple way to initialize an instVar on its first read access? Like a #notYetInitialized: callback to the instVar-holding receiver. Instead, we get an MNU on UndefiniedObject ...
>
> (Why? Performance reasons for a little project of mine.)
>
> Best,
> Marcel
>



Reply | Threaded
Open this post in threaded view
|

Re: MNU for ifNil: to preserve quick returns? :-)

fniephaus
In reply to this post by Jakob Reschke-2
On Tue, Jul 21, 2020 at 12:07 PM Jakob Reschke <[hidden email]> wrote:
Hi Marcel,

Might be cool if the JIT or Scorch emitted code that is equivalent to
a quick return, but with a low-level nil-guard in place. Like a
quick-return-if-not-nil primitive code.

In TruffleSqueak, we profile how often a branch is taken. The init branch is only taken once, so it's unlikely to be part of the compiled code emitted by the JIT. The decrease in code size then makes it very likely that inlining is going to happen. Not sure if the OpenSmalltalkVM has similar optimizations for this in place.

Fabio
 

Is eager initialization out of the question for you?

If all your instVars were initialized on the first read of one of
them, you could also change the class of the object after the lazy
initialization, and the new class would have quick accessors. For
added fanciness, you could auto-generate the "optimized" class and
such accessors in both classes. Though I am totally not sure whether
it is worth the effort or improves the performance at all (since the
call sites are then polymorphic).

notYetInitialized: sounds strange to me, since you could send the
getter in one place and actually use the answer in a totally different
place (where your MNU happens). You could eager-initialize and return
some special case proxy instead of nil that is bound to the original
receiver and takes care of the lazy initialization when called.

Kind regards,
Jakob

Am Di., 21. Juli 2020 um 10:36 Uhr schrieb Marcel Taeumel
<[hidden email]>:
>
> Hi all!
>
> I can choose to initialize an instVar eagerly in #initialize or lazily in its accessor via #ifNil:. Yet, the latter requires me to change that accessor to something not being a quick return.
>
> Could there be a simple way to initialize an instVar on its first read access? Like a #notYetInitialized: callback to the instVar-holding receiver. Instead, we get an MNU on UndefiniedObject ...
>
> (Why? Performance reasons for a little project of mine.)
>
> Best,
> Marcel
>



Reply | Threaded
Open this post in threaded view
|

Re: MNU for ifNil: to preserve quick returns? :-)

timrowledge
In reply to this post by marcel.taeumel


> On 2020-07-21, at 1:36 AM, Marcel Taeumel <[hidden email]> wrote:
>
> I can choose to initialize an instVar eagerly in #initialize or lazily in its accessor via #ifNil:. Yet, the latter requires me to change that accessor to something not being a quick return.

I've always been a bit ambivalent about the lazy initialisation stuff; not that it doesn't have uses. The problematic bit in my experience is tied to the lack of properly private messages and the disappointing propensity of people to treat Smalltalk as C code.

To explain: one decides to have lazy init for an instvar and so creates a methods named as the instvar that does the nil check and init dance. Great - now you can write
`self foobleDong`
and guarantee to get a useful answer. The problem now is that you have made your class into little more than a C struct. Any old Thomas, Richard or Harold can send #foobleDong and get at the internal state of your object. I don't like that.
*If* we had private methods one could mark foobleDong as private and thereby safely use it internally.

I see far too much 'Cmalltalk' where messages are being sent as if they were C struct accessor operators. I really hate seeing
`myThing foo fum bar baz bing: myThing foo fum bar baz bing + 1`



tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
"Bother!" said Pooh, as he stood up to his waist in a cow pat.



Reply | Threaded
Open this post in threaded view
|

Re: MNU for ifNil: to preserve quick returns? :-)

Karl Ramberg
Tim,
You can discourage non private use if you write them like this:
foo
 foo ifNil:[foo := OrderedCollection new].
 ^nil

/s

Best,
Karl



On Tue, Jul 21, 2020 at 7:08 PM tim Rowledge <[hidden email]> wrote:


> On 2020-07-21, at 1:36 AM, Marcel Taeumel <[hidden email]> wrote:
>
> I can choose to initialize an instVar eagerly in #initialize or lazily in its accessor via #ifNil:. Yet, the latter requires me to change that accessor to something not being a quick return.

I've always been a bit ambivalent about the lazy initialisation stuff; not that it doesn't have uses. The problematic bit in my experience is tied to the lack of properly private messages and the disappointing propensity of people to treat Smalltalk as C code.

To explain: one decides to have lazy init for an instvar and so creates a methods named as the instvar that does the nil check and init dance. Great - now you can write
`self foobleDong`
and guarantee to get a useful answer. The problem now is that you have made your class into little more than a C struct. Any old Thomas, Richard or Harold can send #foobleDong and get at the internal state of your object. I don't like that.
*If* we had private methods one could mark foobleDong as private and thereby safely use it internally.

I see far too much 'Cmalltalk' where messages are being sent as if they were C struct accessor operators. I really hate seeing
`myThing foo fum bar baz bing: myThing foo fum bar baz bing + 1`



tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
"Bother!" said Pooh, as he stood up to his waist in a cow pat.





Reply | Threaded
Open this post in threaded view
|

Re: MNU for ifNil: to preserve quick returns? :-)

marcel.taeumel
In reply to this post by timrowledge
Hi Tim.

*If* we had private methods one could mark foobleDong as private and thereby safely use it internally.

As long as programmers cannot make their intent clear with a "private" category or "pvt"-prefix in selectors or just by intentionally (!) using instVars without accessors, having extra annotations for lookup visibility (e.g. public/private/protected) will not make things any better as they are now. We have idioms and patterns for this already.

Sure, programmers that keep on ignoring an interface's intent would be punished if such lookup visibility would be enforced. However, I don't think that's a good way to move forward with Squeak/Smalltalk. ;-) It would lock up the system in a way that might impair liveness and exploration.

Instead, tools can help programmers discover and correct their mistakes. Code critiques, linting tools, code browsers w/ embedded run-time information, ...

Best,
Marcel

Am 21.07.2020 19:08:55 schrieb tim Rowledge <[hidden email]>:



> On 2020-07-21, at 1:36 AM, Marcel Taeumel wrote:
>
> I can choose to initialize an instVar eagerly in #initialize or lazily in its accessor via #ifNil:. Yet, the latter requires me to change that accessor to something not being a quick return.

I've always been a bit ambivalent about the lazy initialisation stuff; not that it doesn't have uses. The problematic bit in my experience is tied to the lack of properly private messages and the disappointing propensity of people to treat Smalltalk as C code.

To explain: one decides to have lazy init for an instvar and so creates a methods named as the instvar that does the nil check and init dance. Great - now you can write
`self foobleDong`
and guarantee to get a useful answer. The problem now is that you have made your class into little more than a C struct. Any old Thomas, Richard or Harold can send #foobleDong and get at the internal state of your object. I don't like that.
*If* we had private methods one could mark foobleDong as private and thereby safely use it internally.

I see far too much 'Cmalltalk' where messages are being sent as if they were C struct accessor operators. I really hate seeing
`myThing foo fum bar baz bing: myThing foo fum bar baz bing + 1`



tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
"Bother!" said Pooh, as he stood up to his waist in a cow pat.