Class side method is missing in obsolete class after the class is removed from system

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

Class side method is missing in obsolete class after the class is removed from system

Nicolás Papagna Maldonado
Im writing some tests that needs to create classes dynamically. During the
tearDown phase, i remove these classes using #removeFromSystem.

I noticed that running these tests became more and more slower as i kept
adding more tests.
Using "Run Profiled" from Test Runner, i found out
ChangesLog>>#logClassRemoved: was responsible of about 43% of the execution
time:

logClassRemoved: annoucement
        annoucement classRemoved acceptsLoggingOfCompilation ifTrue: [
                self logChange: 'Smalltalk globals removeClassNamed: #',
annoucement
classRemoved name
        ].

Based on that, i overrided #acceptsLoggingOfCompilation on the new classes
to avoid these changes being written down to disk (the classes are
disposable after all), but ChangeSet kept doing it.

I confirmed this by inspecting annoucement classRemoved
acceptsLoggingOfCompilation which returns true, ignoring the overriding
implementation i provided.

#acceptsLoggingOfCompilation overriding implementation seems to be lost
during the #removeFromSystem call. Specifically, during Behavior>>#obsolete,
which is called during

Class>>#obsolete
        "Change the receiver and all of its subclasses to an obsolete
class."
        self == Object
                ifTrue: [^self error: 'Object is NOT obsolete'].
        self setName: 'AnObsolete' , self name.
        Object class instSize + 1 to: self classSide instSize do:
                [:i | self instVarAt: i put: nil]. "Store nil over class
instVars."
        self classPool: nil.
        self sharedPools: nil.
        self hasClassSide ifTrue: [ self theMetaClass obsolete]. <=======
HERE
        self propertyAt: #obsolete put: true.
        super obsolete.

When i checked Behavior>>#obsolete, i found out the method dictionary is
emptied, losing my implementation of #acceptsLoggingOfCompilation

Behavior>>obsolete
        "Invalidate and recycle local methods,
        e.g., zap the method dictionary if can be done safely."
        self canZapMethodDictionary
                ifTrue: [self methodDict: self emptyMethodDictionary].
<======= HERE
        self hasTraitComposition ifTrue: [
                self traitComposition traits do: [:each |
                        each removeUser: self]]

I don't know if this is by design or not, but it seems that the class that
gets announced when removed, is not exactly the same as the original.

Any thoughts/recommendations?



--
Sent from: http://forum.world.st/Pharo-Smalltalk-Developers-f1294837.html

Reply | Threaded
Open this post in threaded view
|

Re: Class side method is missing in obsolete class after the class is removed from system

Stephane Ducasse-3
do you know that you can create class silently? so that you do not
have to remove them from the log?

Stef

On Sat, Sep 23, 2017 at 10:33 PM, Nicolás Papagna Maldonado
<[hidden email]> wrote:

> Im writing some tests that needs to create classes dynamically. During the
> tearDown phase, i remove these classes using #removeFromSystem.
>
> I noticed that running these tests became more and more slower as i kept
> adding more tests.
> Using "Run Profiled" from Test Runner, i found out
> ChangesLog>>#logClassRemoved: was responsible of about 43% of the execution
> time:
>
> logClassRemoved: annoucement
>         annoucement classRemoved acceptsLoggingOfCompilation ifTrue: [
>                 self logChange: 'Smalltalk globals removeClassNamed: #',
> annoucement
> classRemoved name
>         ].
>
> Based on that, i overrided #acceptsLoggingOfCompilation on the new classes
> to avoid these changes being written down to disk (the classes are
> disposable after all), but ChangeSet kept doing it.
>
> I confirmed this by inspecting annoucement classRemoved
> acceptsLoggingOfCompilation which returns true, ignoring the overriding
> implementation i provided.
>
> #acceptsLoggingOfCompilation overriding implementation seems to be lost
> during the #removeFromSystem call. Specifically, during Behavior>>#obsolete,
> which is called during
>
> Class>>#obsolete
>         "Change the receiver and all of its subclasses to an obsolete
> class."
>         self == Object
>                 ifTrue: [^self error: 'Object is NOT obsolete'].
>         self setName: 'AnObsolete' , self name.
>         Object class instSize + 1 to: self classSide instSize do:
>                 [:i | self instVarAt: i put: nil]. "Store nil over class
> instVars."
>         self classPool: nil.
>         self sharedPools: nil.
>         self hasClassSide ifTrue: [ self theMetaClass obsolete]. <=======
> HERE
>         self propertyAt: #obsolete put: true.
>         super obsolete.
>
> When i checked Behavior>>#obsolete, i found out the method dictionary is
> emptied, losing my implementation of #acceptsLoggingOfCompilation
>
> Behavior>>obsolete
>         "Invalidate and recycle local methods,
>         e.g., zap the method dictionary if can be done safely."
>         self canZapMethodDictionary
>                 ifTrue: [self methodDict: self emptyMethodDictionary].
> <======= HERE
>         self hasTraitComposition ifTrue: [
>                 self traitComposition traits do: [:each |
>                         each removeUser: self]]
>
> I don't know if this is by design or not, but it seems that the class that
> gets announced when removed, is not exactly the same as the original.
>
> Any thoughts/recommendations?
>
>
>
> --
> Sent from: http://forum.world.st/Pharo-Smalltalk-Developers-f1294837.html
>

Reply | Threaded
Open this post in threaded view
|

Re: Class side method is missing in obsolete class after the class is removed from system

Nicolás Papagna Maldonado
Thanks Stef!

I tried creating classes using SystemAnnouncer uniqueInstance
suspendAllWhile: but this skips all subscribers, not only ChangeSet.

That means that, say, RPackageTag instances won't contain the new class.

Will use a workaround for now, as this is not the core of the thing im
working on.



--
Sent from: http://forum.world.st/Pharo-Smalltalk-Developers-f1294837.html