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 |
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 > |
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 |
Free forum by Nabble | Edit this page |