Skip to content

Commit

Permalink
Added new profiler and refactor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jordanmontt committed Sep 29, 2023
1 parent b91b4f2 commit 151bfb8
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 143 deletions.
89 changes: 89 additions & 0 deletions src/IllimaniProfiler-Tests/IllAbstractProfilerTest.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
Class {
#name : 'IllAbstractProfilerTest',
#superclass : 'TestCase',
#instVars : [
'profiler'
],
#category : 'IllimaniProfiler-Tests-Finalization-Profiler',
#package : 'IllimaniProfiler-Tests',
#tag : 'Finalization-Profiler'
}

{ #category : 'testing' }
IllAbstractProfilerTest class >> isAbstract [

^ self = IllAbstractProfilerTest
]

{ #category : 'running' }
IllAbstractProfilerTest >> profilerClass [

^ self subclassResponsibility
]

{ #category : 'running' }
IllAbstractProfilerTest >> setUp [

super setUp.
profiler := self profilerClass new
]

{ #category : 'running' }
IllAbstractProfilerTest >> tearDown [

profiler forceUninstall.
profiler := nil.
super tearDown
]

{ #category : 'tests' }
IllAbstractProfilerTest >> testOpen [
"This is a smoke test"

profiler profileOn: [ 5 timesRepeat: [ self profilerClass new ] ].
profiler open window close
]

{ #category : 'tests' }
IllAbstractProfilerTest >> testProfileOnSimple [

profiler profileOn: [ 10 timesRepeat: [ IllFinalizationProfiler new ] ].
self assert: profiler objectAllocations size > 10
]

{ #category : 'tests' }
IllAbstractProfilerTest >> testSamplingRate [

| allocatedByteSrings |
"Sampling is not enable for the moment"
self flag: 'Skip'.
self skip.

profiler
samplingRate: 33;
profileOn: [ 90 timesRepeat: [ ByteString new ] ].

allocatedByteSrings := (profiler objectAllocations select:
[ :e | e allocatedObjectClass = ByteString ]) size.

"We are cheking in this range becase the profiler makes some allocations that are
necessary for the profiler to work, like Durations objects. So we cannot chack that the
allocations are exacty 1/3 of the total."
self assert: (allocatedByteSrings >= 30) & (allocatedByteSrings < 40)
]

{ #category : 'tests' }
IllAbstractProfilerTest >> testSamplingRateVariable [

"By default, do not sample"
self assert: profiler samplingRate equals: 1.

"Sample at 20%"
profiler samplingRate: 20.
"Sample at 20% is the same as sample each 5 allocations"
self assert: profiler samplingRate equals: 5.

"Do not sample. The same as sampling 100%".
profiler samplingRate: 100.
self assert: profiler samplingRate equals: 1.
]
79 changes: 10 additions & 69 deletions src/IllimaniProfiler-Tests/IllAllocationProfilerTest.class.st
Original file line number Diff line number Diff line change
@@ -1,97 +1,38 @@
Class {
#name : 'IllAllocationProfilerTest',
#superclass : 'TestCase',
#instVars : [
'illimani'
],
#superclass : 'IllAbstractProfilerTest',
#category : 'IllimaniProfiler-Tests-Allocations-Profiler',
#package : 'IllimaniProfiler-Tests',
#tag : 'Allocations-Profiler'
}

{ #category : 'running' }
IllAllocationProfilerTest >> setUp [
IllAllocationProfilerTest >> profilerClass [

super setUp.
illimani := IllAllocationProfiler new
]

{ #category : 'running' }
IllAllocationProfilerTest >> tearDown [

illimani forceUninstall.
illimani := nil.
super tearDown
^ IllAllocationProfiler
]

{ #category : 'tests' }
IllAllocationProfilerTest >> testProfileOnCopyExecutionStack [

illimani
profiler
copyExecutionStack;
profileOn: [ 10 timesRepeat: [ IllAllocationProfiler new ] ].

"Take one random allocation to check"
self assert: illimani objectAllocations last context class equals: Context.
self assert: profiler objectAllocations last context class equals: Context.

self assert: illimani objectAllocations size > 100.
illimani objectAllocations do: [ :alloc | "Stack was copied"
self assert: profiler objectAllocations size > 100.
profiler objectAllocations do: [ :alloc | "Stack was copied"
self assert: alloc context class equals: Context ]
]

{ #category : 'tests' }
IllAllocationProfilerTest >> testProfileOnSimple [

illimani profileOn: [
OrderedCollection new.
OrderedCollection new.
OrderedCollection new.
Point new.
Rectangle new ].

"Greater because the profiler makes 3 allocations"
self assert: illimani objectAllocations size > 5
]

{ #category : 'tests' }
IllAllocationProfilerTest >> testProfileOnSimpleMoreAllocations [

illimani profileOn: [ 1000 timesRepeat: [ IllAllocationProfiler new ] ].
profiler profileOn: [ 1000 timesRepeat: [ IllAllocationProfiler new ] ].

self assert: illimani objectAllocations size > 1000.
illimani objectAllocations do: [ :alloc |
self assert: profiler objectAllocations size > 1000.
profiler objectAllocations do: [ :alloc |
self assert: alloc allocatedObjectClass isClass ]
]

{ #category : 'tests' }
IllAllocationProfilerTest >> testSamplingRate [

| allocatedByteSrings |
illimani
samplingRate: 33;
profileOn: [ 90 timesRepeat: [ ByteString new ] ].

allocatedByteSrings := (illimani objectAllocations select:
[ :e | e allocatedObjectClass = ByteString ]) size.

"We are cheking in this range becase the profiler makes some allocations that are
necessary for the profiler to work, like Durations objects. So we cannot chack that the
allocations are exacty 1/3 of the total."
self assert: (allocatedByteSrings >= 30) & (allocatedByteSrings < 40)
]

{ #category : 'tests' }
IllAllocationProfilerTest >> testSamplingRateVariable [

"By default, do not sample"
self assert: illimani samplingRate equals: 1.

"Sample at 20%"
illimani samplingRate: 20.
"Sample at 20% is the same as sample each 5 allocations"
self assert: illimani samplingRate equals: 5.

"Do not sample. The same as sampling 100%".
illimani samplingRate: 100.
self assert: illimani samplingRate equals: 1.
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Class {
#name : 'IllAllocationStatisticsProfilerTest',
#superclass : 'IllAbstractProfilerTest',
#category : 'IllimaniProfiler-Tests-Finalization-Profiler',
#package : 'IllimaniProfiler-Tests',
#tag : 'Finalization-Profiler'
}

{ #category : 'running' }
IllAllocationStatisticsProfilerTest >> profilerClass [

^ IllAllocationStatisticsProfiler
]
52 changes: 9 additions & 43 deletions src/IllimaniProfiler-Tests/IllFinalizationProfilerTest.class.st
Original file line number Diff line number Diff line change
@@ -1,40 +1,28 @@
Class {
#name : 'IllFinalizationProfilerTest',
#superclass : 'TestCase',
#instVars : [
'finalizationProfiler'
],
#superclass : 'IllAbstractProfilerTest',
#category : 'IllimaniProfiler-Tests-Finalization-Profiler',
#package : 'IllimaniProfiler-Tests',
#tag : 'Finalization-Profiler'
}

{ #category : 'running' }
IllFinalizationProfilerTest >> setUp [
IllFinalizationProfilerTest >> profilerClass [

super setUp.
finalizationProfiler := IllFinalizationProfiler new
]

{ #category : 'running' }
IllFinalizationProfilerTest >> tearDown [

finalizationProfiler forceUninstall.
finalizationProfiler := nil.
super tearDown
^ IllFinalizationProfiler
]

{ #category : 'tests' }
IllFinalizationProfilerTest >> testProfileOn [

finalizationProfiler profileOn: [ 10 timesRepeat: [ IllFinalizationProfiler new ] ].
profiler profileOn: [ 10 timesRepeat: [ IllFinalizationProfiler new ] ].

"We let the GC run for N times to clean the not referenced objects. Because of the
implementation of ephemerons, they can have hard references between them so it is
necessary to run the GC several times "
10 timesRepeat: [ Smalltalk garbageCollect ].

self assert: finalizationProfiler objectAllocations size > 10
self assert: profiler objectAllocations size > 10
]

{ #category : 'tests' }
Expand All @@ -43,40 +31,18 @@ IllFinalizationProfilerTest >> testProfileOnFinalizesCorrectly [
| timeNow |

timeNow := Time microsecondClockValue.
finalizationProfiler profileOn: [ 10 timesRepeat: [ IllFinalizationProfiler new ] ].
profiler profileOn: [ 10 timesRepeat: [ IllFinalizationProfiler new ] ].

"We let the GC run for N times to clean the not referenced objects. Because of the
implementation of ephemerons, they can have hard references between them so it is
necessary to run the GC several times "
10 timesRepeat: [ Smalltalk garbageCollect ].

self
assert: finalizationProfiler objectAllocations size
equals: (finalizationProfiler objectAllocations select: [ :e | e finalizationTime isNotNil]) size.
assert: profiler objectAllocations size
equals: (profiler objectAllocations select: [ :e | e finalizationTime isNotNil]) size.

finalizationProfiler objectAllocations do: [ :alloc |
profiler objectAllocations do: [ :alloc |
"Finalization time must be after timeNow variable"
self assert: alloc finalizationTime > timeNow ]
]

{ #category : 'tests' }
IllFinalizationProfilerTest >> testSamplingRate [

| allocatedByteSrings |
finalizationProfiler
samplingRate: 20;
profileOn: [ 20 timesRepeat: [ ByteString new ] ].

"We let the GC run for N times to clean the not referenced objects. Because of the
implementation of ephemerons, they can have hard references between them so it is
necessary to run the GC several times "
20 timesRepeat: [ Smalltalk garbageCollect ].

allocatedByteSrings := (finalizationProfiler objectAllocations select:
[ :e | e allocatedObjectClass = ByteString ]) size.

"We are cheking in this range becase the profiler makes some allocations that are
necessary for the profiler to work, like Durations objects. So we cannot check that the
allocations are exacty 1/5 of the total."
self assert: allocatedByteSrings < 7
]
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
Class {
#name : 'IllFinalizationProfilerUnconstructedCollectionTest',
#superclass : 'TestCase',
#instVars : [
'profiler'
],
#superclass : 'IllAbstractProfilerTest',
#category : 'IllimaniProfiler-Tests-Finalization-Profiler',
#package : 'IllimaniProfiler-Tests',
#tag : 'Finalization-Profiler'
Expand All @@ -18,18 +15,9 @@ IllFinalizationProfilerUnconstructedCollectionTest >> assertAllocationResult: al
]

{ #category : 'running' }
IllFinalizationProfilerUnconstructedCollectionTest >> setUp [
IllFinalizationProfilerUnconstructedCollectionTest >> profilerClass [

super setUp.
profiler := IllFinalizationUnprocessedAllocationsProfiler new
]

{ #category : 'running' }
IllFinalizationProfilerUnconstructedCollectionTest >> tearDown [

profiler forceUninstall.
profiler := nil.
super tearDown
^ IllFinalizationUnprocessedAllocationsProfiler
]

{ #category : 'tests' }
Expand Down
14 changes: 14 additions & 0 deletions src/IllimaniProfiler/IllAbstractProfiler.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ Class {
#tag : 'Instrumentation'
}

{ #category : 'accessing - statistics' }
IllAbstractProfiler >> allocatedMemoryRatePerSecond [

^ self stats totalAllocatedMemory
/ (Duration microSeconds: totalTime) totalSeconds asFloat
]

{ #category : 'accessing - statistics' }
IllAbstractProfiler >> allocationRatePerSecond [

^ self stats totalAllocatedObjects
/ (Duration microSeconds: totalTime) totalSeconds asFloat
]

{ #category : 'accessing - statistics' }
IllAbstractProfiler >> beginningOfProfilingTime [

Expand Down
14 changes: 0 additions & 14 deletions src/IllimaniProfiler/IllAllocationStatisticsProfiler.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,6 @@ Class {
#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 [

Expand Down
4 changes: 2 additions & 2 deletions src/IllimaniUI/AllocationSummaryPresenter.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ Class {
{ #category : 'layout' }
AllocationSummaryPresenter >> allocatedMemoryRateString [

^ profiler stats allocatedMemoryRatePerSecond asInteger humanReadableByteSizeString
^ profiler allocatedMemoryRatePerSecond asInteger humanReadableByteSizeString
, ' per second'
]

{ #category : 'layout' }
AllocationSummaryPresenter >> allocationRateString [

| rate |
rate := profiler stats allocationRatePerSecond.
rate := profiler allocationRatePerSecond.
^ rate asInteger asStringWithCommas , ' allocations per second'
]

Expand Down

0 comments on commit 151bfb8

Please sign in to comment.