Christoph Thiede uploaded a new version of System to project The Inbox: http://source.squeak.org/inbox/System-ct.1443.mcz
==================== Summary ====================
Name: System-ct.1443 Author: ct Time: 9 January 2024, 7:19:27.926382 pm UUID: 47928ca5-1746-434d-85a6-332abb38a39b Ancestors: System-dtl.1442
Speeds up SpaceTally by >50% by avoiding expensive pushThisContext. Note that this mainly benefits large objects but has no significant effect on systemWideSpaceTally.
array := 1000000 timesCollect: [Morph new]. "before:" [SpaceTally new spaceForInstance: array depth: 1] benchFor: 30 seconds '0.628 per second. 1.59 seconds per run. 63.71328 % GC time.' "after:" [SpaceTally new spaceForInstance: array depth: 1] benchFor: 30 seconds. '1.28 per second. 779 milliseconds per run. 42.51465 % GC time.'
=============== Diff against System-dtl.1442 ===============
Item was changed: Object subclass: #SpaceTally instanceVariableNames: 'results depth' + classVariableNames: 'Mirror' - classVariableNames: '' poolDictionaries: '' category: 'System-Tools'!
!SpaceTally commentStamp: '<historical>' prior: 0! I'm responsible to help getting information about system space usage. The information I compute is represented by a spaceTallyItem.
Here are some examples to inspect: SpaceTally new spaceTally: (Array with: TextMorph with: Point). SpaceTally new systemWideSpaceTally. SpaceTally new depth: 2; spaceTally: (PackageInfo named: #Morphic) classes. SpaceTally new depth: 1; spaceTally: (PackageInfo named: #Monticello) classes. "Includes cached source code" SpaceTally new spaceForInstancesOf: Form depth: 1. "Includes footprint for bitmaps"!
Item was added: + ----- Method: SpaceTally class>>initialize (in category 'class initialization') ----- + initialize + + "Provides access to mirror primitives. Cache this once to avoid expensive thisContext at every access." + Mirror := Context newForMethod: CompiledMethod toReturnSelf. "avoid dangling references to the current context or stack"!
Item was changed: ----- Method: SpaceTally>>spaceForInstance:depth:seen: (in category 'instance size') ----- spaceForInstance: anObject depth: anInteger seen: seenObjectsOrNil
+ | class basicSize currentDepth total | - | ctxt class basicSize currentDepth total | seenObjectsOrNil ifNotNil: [ (seenObjectsOrNil ifAbsentAdd: anObject) ifFalse: [^ 0]]. + class := Mirror objectClass: anObject. - ctxt := thisContext. - class := ctxt objectClass: anObject. basicSize := 0. total := class isVariable + ifTrue: [class byteSizeOfInstanceOfSize: (basicSize := Mirror objectSize: anObject)] - ifTrue: [class byteSizeOfInstanceOfSize: (basicSize := ctxt objectSize: anObject)] ifFalse: [class isImmediateClass ifTrue: [0] ifFalse: [class byteSizeOfInstance]]. (currentDepth := anInteger - 1) >= 0 ifTrue: [ anObject isCompiledCode ifTrue: [ anObject literalsDo: [:literal | total := total + (self spaceForInstance: literal depth: currentDepth seen: seenObjectsOrNil)]] ifFalse: [ (class instSpec between: 2 and: 4) ifTrue: [ "only indexable objects, no bytes etc." 1 to: basicSize do: [:index | + total := total + (self spaceForInstance: (Mirror object: anObject basicAt: index) depth: currentDepth seen: seenObjectsOrNil)]]. - total := total + (self spaceForInstance: (ctxt object: anObject basicAt: index) depth: currentDepth seen: seenObjectsOrNil)]]. 1 to: class instSize do: [:index | + total := total + (self spaceForInstance: (Mirror object: anObject instVarAt: index) depth: currentDepth seen: seenObjectsOrNil)]]]. - total := total + (self spaceForInstance: (ctxt object: anObject instVarAt: index) depth: currentDepth seen: seenObjectsOrNil)]]]. ^ total!
Well, those "mirror primitives" are also implemented on Object but avoid a regular message send, which might be overwritten by some subclass. They rely on each primitive accessing the top n arguments from the stack, but popping *all* arguments before return. Even one extra, unused receiver like thisContext. So, any receiver can implement those primitives.
We could put them on the class side of Context or Object ... or is there more to it?
Aaaand Object >> #perform:withArguments:inSuperclass: has different error codes compared with Context >> #object:perform:withArguments:inClass: ... hmm...
For this proposed change here to SpaceTally: +1 but I would reset the Mirror (CompiledMethod toReturnSelf) on #cleanUp: to support Compiler changes and #recompileAll etc.
Best, Marcel
Am 09.01.2024 19:19:52 schrieb commits@source.squeak.org commits@source.squeak.org:
Christoph Thiede uploaded a new version of System to project The Inbox: http://source.squeak.org/inbox/System-ct.1443.mcz
==================== Summary ====================
Name: System-ct.1443 Author: ct Time: 9 January 2024, 7:19:27.926382 pm UUID: 47928ca5-1746-434d-85a6-332abb38a39b Ancestors: System-dtl.1442
Speeds up SpaceTally by >50% by avoiding expensive pushThisContext. Note that this mainly benefits large objects but has no significant effect on systemWideSpaceTally.
array := 1000000 timesCollect: [Morph new]. "before:" [SpaceTally new spaceForInstance: array depth: 1] benchFor: 30 seconds '0.628 per second. 1.59 seconds per run. 63.71328 % GC time.' "after:" [SpaceTally new spaceForInstance: array depth: 1] benchFor: 30 seconds. '1.28 per second. 779 milliseconds per run. 42.51465 % GC time.'
=============== Diff against System-dtl.1442 ===============
Item was changed: Object subclass: #SpaceTally instanceVariableNames: 'results depth' + classVariableNames: 'Mirror' - classVariableNames: '' poolDictionaries: '' category: 'System-Tools'!
!SpaceTally commentStamp: '' prior: 0! I'm responsible to help getting information about system space usage. The information I compute is represented by a spaceTallyItem.
Here are some examples to inspect: SpaceTally new spaceTally: (Array with: TextMorph with: Point). SpaceTally new systemWideSpaceTally. SpaceTally new depth: 2; spaceTally: (PackageInfo named: #Morphic) classes. SpaceTally new depth: 1; spaceTally: (PackageInfo named: #Monticello) classes. "Includes cached source code" SpaceTally new spaceForInstancesOf: Form depth: 1. "Includes footprint for bitmaps"!
Item was added: + ----- Method: SpaceTally class>>initialize (in category 'class initialization') ----- + initialize + + "Provides access to mirror primitives. Cache this once to avoid expensive thisContext at every access." + Mirror := Context newForMethod: CompiledMethod toReturnSelf. "avoid dangling references to the current context or stack"!
Item was changed: ----- Method: SpaceTally>>spaceForInstance:depth:seen: (in category 'instance size') ----- spaceForInstance: anObject depth: anInteger seen: seenObjectsOrNil
+ | class basicSize currentDepth total | - | ctxt class basicSize currentDepth total | seenObjectsOrNil ifNotNil: [ (seenObjectsOrNil ifAbsentAdd: anObject) ifFalse: [^ 0]]. + class := Mirror objectClass: anObject. - ctxt := thisContext. - class := ctxt objectClass: anObject. basicSize := 0. total := class isVariable + ifTrue: [class byteSizeOfInstanceOfSize: (basicSize := Mirror objectSize: anObject)] - ifTrue: [class byteSizeOfInstanceOfSize: (basicSize := ctxt objectSize: anObject)] ifFalse: [class isImmediateClass ifTrue: [0] ifFalse: [class byteSizeOfInstance]]. (currentDepth := anInteger - 1) >= 0 ifTrue: [ anObject isCompiledCode ifTrue: [ anObject literalsDo: [:literal | total := total + (self spaceForInstance: literal depth: currentDepth seen: seenObjectsOrNil)]] ifFalse: [ (class instSpec between: 2 and: 4) ifTrue: [ "only indexable objects, no bytes etc." 1 to: basicSize do: [:index | + total := total + (self spaceForInstance: (Mirror object: anObject basicAt: index) depth: currentDepth seen: seenObjectsOrNil)]]. - total := total + (self spaceForInstance: (ctxt object: anObject basicAt: index) depth: currentDepth seen: seenObjectsOrNil)]]. 1 to: class instSize do: [:index | + total := total + (self spaceForInstance: (Mirror object: anObject instVarAt: index) depth: currentDepth seen: seenObjectsOrNil)]]]. - total := total + (self spaceForInstance: (ctxt object: anObject instVarAt: index) depth: currentDepth seen: seenObjectsOrNil)]]]. ^ total!
squeak-dev@lists.squeakfoundation.org