From b91b4f2119709d42257ccb1d4c87adf42b5efe15 Mon Sep 17 00:00:00 2001 From: jordanmontt Date: Fri, 29 Sep 2023 11:49:52 +0200 Subject: [PATCH] Added new profiler to get the allocation rate --- ...ofilerUnconstructedCollectionTest.class.st | 12 +- .../AllocationBasicInfoModel.class.st | 60 +++++++++ .../AllocationFinalizationInfoModel.class.st | 79 +++++++++++ .../AllocationSiteInfoModel.class.st | 2 +- .../BasicAllocationInfoModel.class.st | 124 ------------------ .../IllAllocationStatisticsProfiler.class.st | 68 ++++++++++ ...ionUnprocessedAllocationsProfiler.class.st | 2 +- .../AllocationSummaryPresenter.class.st | 28 +++- .../IllAbstractProfiler.extension.st | 2 +- ...IllAllocationStatisticsProfilerUI.class.st | 30 +++++ 10 files changed, 269 insertions(+), 138 deletions(-) create mode 100644 src/IllimaniProfiler/AllocationBasicInfoModel.class.st create mode 100644 src/IllimaniProfiler/AllocationFinalizationInfoModel.class.st delete mode 100644 src/IllimaniProfiler/BasicAllocationInfoModel.class.st create mode 100644 src/IllimaniProfiler/IllAllocationStatisticsProfiler.class.st create mode 100644 src/IllimaniUI/IllAllocationStatisticsProfilerUI.class.st diff --git a/src/IllimaniProfiler-Tests/IllFinalizationProfilerUnconstructedCollectionTest.class.st b/src/IllimaniProfiler-Tests/IllFinalizationProfilerUnconstructedCollectionTest.class.st index 5dbf5a2..a554b23 100644 --- a/src/IllimaniProfiler-Tests/IllFinalizationProfilerUnconstructedCollectionTest.class.st +++ b/src/IllimaniProfiler-Tests/IllFinalizationProfilerUnconstructedCollectionTest.class.st @@ -85,7 +85,7 @@ IllFinalizationProfilerUnconstructedCollectionTest >> testObjectAllocations [ profiler registerAllocation: allocation. profiler finalize: allocation. - allocationHolderExpected := BasicAllocationInfoModel new + allocationHolderExpected := AllocationFinalizationInfoModel new allocatedObjectClass: allocation class; sizeInBytes: allocation sizeInMemory; yourself. @@ -101,7 +101,7 @@ IllFinalizationProfilerUnconstructedCollectionTest >> testObjectAllocationsTwoOb allocation := Array new. profiler registerAllocation: allocation. profiler finalize: allocation. - allocationHolderExpected1 := BasicAllocationInfoModel new + allocationHolderExpected1 := AllocationFinalizationInfoModel new allocatedObjectClass: allocation class; sizeInBytes: allocation sizeInMemory; yourself. @@ -109,7 +109,7 @@ IllFinalizationProfilerUnconstructedCollectionTest >> testObjectAllocationsTwoOb allocation := OrderedCollection new. profiler registerAllocation: allocation. profiler finalize: allocation. - allocationHolderExpected2 := BasicAllocationInfoModel new + allocationHolderExpected2 := AllocationFinalizationInfoModel new allocatedObjectClass: allocation class; sizeInBytes: allocation sizeInMemory; yourself. @@ -125,7 +125,7 @@ IllFinalizationProfilerUnconstructedCollectionTest >> testObjectAllocationsTwoOb allocation := Array new. profiler registerAllocation: allocation. profiler finalize: allocation. - allocationHolderExpected1 := BasicAllocationInfoModel new + allocationHolderExpected1 := AllocationFinalizationInfoModel new allocatedObjectClass: allocation class; sizeInBytes: allocation sizeInMemory; yourself. @@ -133,7 +133,7 @@ IllFinalizationProfilerUnconstructedCollectionTest >> testObjectAllocationsTwoOb allocation := OrderedCollection new. profiler registerAllocation: allocation. profiler finalize: allocation. - allocationHolderExpected2 := BasicAllocationInfoModel new + allocationHolderExpected2 := AllocationFinalizationInfoModel new allocatedObjectClass: allocation class; sizeInBytes: allocation sizeInMemory; yourself. @@ -151,7 +151,7 @@ IllFinalizationProfilerUnconstructedCollectionTest >> testObjectAllocationsWithT profiler registerAllocation: allocation. profiler finalize: allocation. - allocationHolderExpected := BasicAllocationInfoModel new + allocationHolderExpected := AllocationFinalizationInfoModel new allocatedObjectClass: allocation class; sizeInBytes: allocation sizeInMemory; yourself. diff --git a/src/IllimaniProfiler/AllocationBasicInfoModel.class.st b/src/IllimaniProfiler/AllocationBasicInfoModel.class.st new file mode 100644 index 0000000..6243575 --- /dev/null +++ b/src/IllimaniProfiler/AllocationBasicInfoModel.class.st @@ -0,0 +1,60 @@ +Class { + #name : 'AllocationBasicInfoModel', + #superclass : 'Object', + #instVars : [ + 'allocatedObjectClass', + 'sizeInBytes' + ], + #category : 'IllimaniProfiler-Model-Allocation', + #package : 'IllimaniProfiler', + #tag : 'Model-Allocation' +} + +{ #category : 'accessing' } +AllocationBasicInfoModel >> allocatedObjectClass [ + + ^ allocatedObjectClass +] + +{ #category : 'accessing' } +AllocationBasicInfoModel >> allocatedObjectClass: anObject [ + + allocatedObjectClass := anObject +] + +{ #category : 'inspector - extensions' } +AllocationBasicInfoModel >> inspectableAssociations [ + + ^ { + ('Allocated Object Class' -> allocatedObjectClass). + ('Memory Size' -> sizeInBytes humanReadableByteSizeString) } +] + +{ #category : 'inspector - extensions' } +AllocationBasicInfoModel >> inspectorExtension: aBuilder [ + + + | tablePresenter elements items | + elements := self inspectableAssociations. + items := elements collect: [ :e | StInspectorAssociationNode hostObject: e ]. + tablePresenter := aBuilder newTable. + tablePresenter + addColumn: (SpStringTableColumn title: 'Name' evaluated: #key); + addColumn: (SpStringTableColumn title: 'Value' evaluated: #value); + items: items; + beResizable. + ^ tablePresenter +] + +{ #category : 'accessing' } +AllocationBasicInfoModel >> sizeInBytes [ + "Returns the size in memory in bytes" + + ^ sizeInBytes +] + +{ #category : 'accessing' } +AllocationBasicInfoModel >> sizeInBytes: aNumber [ + + sizeInBytes := aNumber +] diff --git a/src/IllimaniProfiler/AllocationFinalizationInfoModel.class.st b/src/IllimaniProfiler/AllocationFinalizationInfoModel.class.st new file mode 100644 index 0000000..78aa604 --- /dev/null +++ b/src/IllimaniProfiler/AllocationFinalizationInfoModel.class.st @@ -0,0 +1,79 @@ +Class { + #name : 'AllocationFinalizationInfoModel', + #superclass : 'AllocationBasicInfoModel', + #instVars : [ + 'finalizationTime', + 'initializationTime' + ], + #category : 'IllimaniProfiler-Model-Allocation', + #package : 'IllimaniProfiler', + #tag : 'Model-Allocation' +} + +{ #category : 'accessing' } +AllocationFinalizationInfoModel >> finalizationTime [ + "In microseconds" + + ^ finalizationTime +] + +{ #category : 'accessing' } +AllocationFinalizationInfoModel >> finalizationTime: anObject [ + "In microseconds" + + finalizationTime := anObject +] + +{ #category : 'finalization' } +AllocationFinalizationInfoModel >> finalize [ + + finalizationTime := Time microsecondClockValue +] + +{ #category : 'accessing' } +AllocationFinalizationInfoModel >> initializationTime [ + "In microseconds" + + ^ initializationTime +] + +{ #category : 'accessing' } +AllocationFinalizationInfoModel >> initializationTime: microsecondsAsInt [ + "In microseconds" + + initializationTime := microsecondsAsInt +] + +{ #category : 'inspector - extensions' } +AllocationFinalizationInfoModel >> inspectableAssociations [ + + ^ super inspectableAssociations , { + ('Initialization timestamp' -> initializationTime). + ('Finalization timestamp' -> finalizationTime). + ('Object''s lifetime' -> self lifetimeAsString) } +] + +{ #category : 'accessing' } +AllocationFinalizationInfoModel >> lifetime [ + + ^ finalizationTime - initializationTime +] + +{ #category : 'accessing' } +AllocationFinalizationInfoModel >> lifetimeAsDuration [ + + ^ Duration microSeconds: self lifetime +] + +{ #category : 'accessing' } +AllocationFinalizationInfoModel >> lifetimeAsString [ + + finalizationTime ifNil: [ ^ '-' ]. + ^ self lifetimeAsDuration humanReadablePrintString +] + +{ #category : 'accessing' } +AllocationFinalizationInfoModel >> timeAsSeconds [ + + ^ initializationTime / 1000000 +] diff --git a/src/IllimaniProfiler/AllocationSiteInfoModel.class.st b/src/IllimaniProfiler/AllocationSiteInfoModel.class.st index b2cd8e3..54f9965 100644 --- a/src/IllimaniProfiler/AllocationSiteInfoModel.class.st +++ b/src/IllimaniProfiler/AllocationSiteInfoModel.class.st @@ -1,6 +1,6 @@ Class { #name : 'AllocationSiteInfoModel', - #superclass : 'BasicAllocationInfoModel', + #superclass : 'AllocationFinalizationInfoModel', #instVars : [ 'context', 'allocatorClass', diff --git a/src/IllimaniProfiler/BasicAllocationInfoModel.class.st b/src/IllimaniProfiler/BasicAllocationInfoModel.class.st deleted file mode 100644 index 3e25e4f..0000000 --- a/src/IllimaniProfiler/BasicAllocationInfoModel.class.st +++ /dev/null @@ -1,124 +0,0 @@ -Class { - #name : 'BasicAllocationInfoModel', - #superclass : 'Object', - #instVars : [ - 'allocatedObjectClass', - 'sizeInBytes', - 'finalizationTime', - 'initializationTime' - ], - #category : 'IllimaniProfiler-Model-Allocation', - #package : 'IllimaniProfiler', - #tag : 'Model-Allocation' -} - -{ #category : 'accessing' } -BasicAllocationInfoModel >> allocatedObjectClass [ - - ^ allocatedObjectClass -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> allocatedObjectClass: anObject [ - - allocatedObjectClass := anObject -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> finalizationTime [ - "In microseconds" - - ^ finalizationTime -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> finalizationTime: anObject [ - "In microseconds" - - finalizationTime := anObject -] - -{ #category : 'finalization' } -BasicAllocationInfoModel >> finalize [ - - finalizationTime := Time microsecondClockValue -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> initializationTime [ - "In microseconds" - - ^ initializationTime -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> initializationTime: microsecondsAsInt [ - "In microseconds" - - initializationTime := microsecondsAsInt -] - -{ #category : 'inspector - extensions' } -BasicAllocationInfoModel >> inspectableAssociations [ - - ^ { - ('Allocated Object Class' -> allocatedObjectClass). - ('Memory Size' -> sizeInBytes humanReadableByteSizeString). - ('Initialization timestamp' -> initializationTime). - ('Finalization timestamp' -> finalizationTime). - ('Object''s lifetime' -> self lifetimeAsString) } -] - -{ #category : 'inspector - extensions' } -BasicAllocationInfoModel >> inspectorExtension: aBuilder [ - - - | tablePresenter elements items | - elements := self inspectableAssociations. - items := elements collect: [ :e | StInspectorAssociationNode hostObject: e ]. - tablePresenter := aBuilder newTable. - tablePresenter - addColumn: (SpStringTableColumn title: 'Name' evaluated: #key); - addColumn: (SpStringTableColumn title: 'Value' evaluated: #value); - items: items; - beResizable. - ^ tablePresenter -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> lifetime [ - - ^ finalizationTime - initializationTime -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> lifetimeAsDuration [ - - ^ Duration microSeconds: self lifetime -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> lifetimeAsString [ - - finalizationTime ifNil: [ ^ '-' ]. - ^ self lifetimeAsDuration humanReadablePrintString -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> sizeInBytes [ - "Returns the size in memory in bytes" - - ^ sizeInBytes -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> sizeInBytes: aNumber [ - - sizeInBytes := aNumber -] - -{ #category : 'accessing' } -BasicAllocationInfoModel >> timeAsSeconds [ - - ^ initializationTime / 1000000 -] diff --git a/src/IllimaniProfiler/IllAllocationStatisticsProfiler.class.st b/src/IllimaniProfiler/IllAllocationStatisticsProfiler.class.st new file mode 100644 index 0000000..2b17b43 --- /dev/null +++ b/src/IllimaniProfiler/IllAllocationStatisticsProfiler.class.st @@ -0,0 +1,68 @@ +Class { + #name : 'IllAllocationStatisticsProfiler', + #superclass : 'IllAbstractProfiler', + #instVars : [ + 'allocationsRegistry', + 'objectAllocations' + ], + #category : 'IllimaniProfiler-Allocation-Profiler', + #package : 'IllimaniProfiler', + #tag : 'Allocation-Profiler' +} + +{ #category : 'accessing - statistics' } +IllAllocationStatisticsProfiler >> allocatedMemoryRatePerSecond [ + + ^ self stats totalAllocatedMemory + / (Duration microSeconds: totalTime) totalSeconds asFloat +] + +{ #category : 'accessing - statistics' } +IllAllocationStatisticsProfiler >> allocationRatePerSecond [ + + ^ self stats totalAllocatedObjects + / (Duration microSeconds: totalTime) totalSeconds asFloat +] + +{ #category : 'initialization' } +IllAllocationStatisticsProfiler >> initialize [ + + super initialize. + allocationsRegistry := OrderedCollection new: 3000000 +] + +{ #category : 'profiling' } +IllAllocationStatisticsProfiler >> internalRegisterAllocation: anObject [ + + allocationsRegistry add: anObject class -> anObject sizeInMemory +] + +{ #category : 'accessing' } +IllAllocationStatisticsProfiler >> objectAllocations [ + + objectAllocations ifNil: [ + objectAllocations := allocationsRegistry collect: [ :assoc | + AllocationBasicInfoModel new + allocatedObjectClass: assoc key; + sizeInBytes: assoc value; + yourself ] ]. + ^ objectAllocations +] + +{ #category : 'accessing - statistics' } +IllAllocationStatisticsProfiler >> stats [ + + ^ self +] + +{ #category : 'accessing' } +IllAllocationStatisticsProfiler >> totalAllocatedMemory [ + + ^ self objectAllocations sum: #sizeInBytes +] + +{ #category : 'accessing' } +IllAllocationStatisticsProfiler >> totalAllocatedObjects [ + + ^ allocationsRegistry size +] diff --git a/src/IllimaniProfiler/IllFinalizationUnprocessedAllocationsProfiler.class.st b/src/IllimaniProfiler/IllFinalizationUnprocessedAllocationsProfiler.class.st index 8155caf..7cb8c83 100644 --- a/src/IllimaniProfiler/IllFinalizationUnprocessedAllocationsProfiler.class.st +++ b/src/IllimaniProfiler/IllFinalizationUnprocessedAllocationsProfiler.class.st @@ -63,7 +63,7 @@ IllFinalizationUnprocessedAllocationsProfiler >> objectAllocations [ unprocessedAllocations doWithIndex: [ :data :index | data = -1 ifTrue: [ | model | - model := allocationsDictionary at: (unprocessedAllocations at: index - 4) ifAbsentPut: [ BasicAllocationInfoModel new ]. + model := allocationsDictionary at: (unprocessedAllocations at: index - 4) ifAbsentPut: [ AllocationFinalizationInfoModel new ]. self processInitialization: model atIndex: index ] ]. unprocessedFinalizations doWithIndex: [ :data :index | diff --git a/src/IllimaniUI/AllocationSummaryPresenter.class.st b/src/IllimaniUI/AllocationSummaryPresenter.class.st index d9d5809..08d84e5 100644 --- a/src/IllimaniUI/AllocationSummaryPresenter.class.st +++ b/src/IllimaniUI/AllocationSummaryPresenter.class.st @@ -9,6 +9,21 @@ Class { #tag : 'Widgets' } +{ #category : 'layout' } +AllocationSummaryPresenter >> allocatedMemoryRateString [ + + ^ profiler stats allocatedMemoryRatePerSecond asInteger humanReadableByteSizeString + , ' per second' +] + +{ #category : 'layout' } +AllocationSummaryPresenter >> allocationRateString [ + + | rate | + rate := profiler stats allocationRatePerSecond. + ^ rate asInteger asStringWithCommas , ' allocations per second' +] + { #category : 'layout' } AllocationSummaryPresenter >> buildTablePresenterOn: associations [ @@ -44,11 +59,14 @@ AllocationSummaryPresenter >> defaultLayout [ { #category : 'layout' } AllocationSummaryPresenter >> generalStatsAssociations [ - ^ { ('Total profiled time' -> (Duration microSeconds: profiler totalProfiledTime) - humanReadableStringWithOnlySeconds). - ('Total allocated objects' -> profiler stats totalAllocatedObjects asStringWithCommas). - ('Total allocated memory' -> profiler stats - totalAllocatedMemory humanReadableByteSizeString) } + ^ { + ('Total profiled time' -> + (Duration microSeconds: profiler totalProfiledTime) humanReadableStringWithOnlySeconds). + ('Total allocated objects' -> profiler stats totalAllocatedObjects asStringWithCommas). + ('Allocations rate' -> self allocationRateString ). + ('Total allocated memory' -> + profiler stats totalAllocatedMemory humanReadableByteSizeString). + ('Allocated memory rate' -> self allocatedMemoryRateString)} ] { #category : 'accessing - model' } diff --git a/src/IllimaniUI/IllAbstractProfiler.extension.st b/src/IllimaniUI/IllAbstractProfiler.extension.st index 1a89f7f..2bc1e47 100644 --- a/src/IllimaniUI/IllAbstractProfiler.extension.st +++ b/src/IllimaniUI/IllAbstractProfiler.extension.st @@ -11,5 +11,5 @@ IllAbstractProfiler >> open [ { #category : '*IllimaniUI' } IllAbstractProfiler >> uiClass [ - ^ self subclassResponsibility + ^ IllAllocationStatisticsProfilerUI ] diff --git a/src/IllimaniUI/IllAllocationStatisticsProfilerUI.class.st b/src/IllimaniUI/IllAllocationStatisticsProfilerUI.class.st new file mode 100644 index 0000000..3adcc2c --- /dev/null +++ b/src/IllimaniUI/IllAllocationStatisticsProfilerUI.class.st @@ -0,0 +1,30 @@ +Class { + #name : 'IllAllocationStatisticsProfilerUI', + #superclass : 'IllAbstractUI', + #category : 'IllimaniUI-Main Presenter', + #package : 'IllimaniUI', + #tag : 'Main Presenter' +} + +{ #category : 'accessing' } +IllAllocationStatisticsProfilerUI >> codeEvaluatorText [ + + ^ 'self objectAllocations' +] + +{ #category : 'initialization' } +IllAllocationStatisticsProfilerUI >> initializeNotebook [ + + notebookPresenter := self newNotebook + addPageTitle: 'Summary' provider: [ self summaryAndEvaluatorPresenter ]; + addPageTitle: 'Allocated Objects' provider: [ self allocatedObjectsTablePresenter ]; + + addPageTitle: 'Evaluator' provider: [ self codeEvaluator ]; + yourself +] + +{ #category : 'initialization - lazy presenters' } +IllAllocationStatisticsProfilerUI >> summaryStatsPresenter [ + + ^ AllocationSummaryPresenter on: profiler +]