MareaHeaderGrey


Abstract

It is important to understand which parts of the system are instantiated but also which are used or unused. We define that a used object is one that receives a message or that is directly used by the VirtualMachine, during a specific period of time. The main challenge here is where to store the mark of each object. Adding an instance variable to Object (the root class of the Smalltalk hierarchy chain) and store there a Boolean object is not possible in Pharo, and the requirement of an extra reference for each object is highly memory consuming. Our solution modifies the Pharo VM so that we can use an empty bit of the object header to mark objects as used. That way we do not use extra memory and it works efficiently. We also modify the code of the VM that implements the message send to turn on the bit when an object receives a message.

Interesting Links

Installation

Take a Pharo image an evaluate:
Gofer new
	squeaksource: 'UsedObjects';
	package: 'ConfigurationOfUsedObjects';
load.
(Smalltalk at: #ConfigurationOfUsedObjects) project lastVersion load. 

Getting Started

The main class is called UnusedObjectDiscoverer and lets you find used objects during an execution. In order to do that:1) You first have to evauate: UnusedObjectDiscoverer current startDiscovery. With that, you mark all objects as unused so that you can start a clean discovery.2) Then, you do things. Run a seaside app, develope, code, etc. 3) Once you are finished and want to see the usage, print or inspect: UnusedObjectDiscoverer current stopDiscoveryAndGetStadistics This will get the statistics and unmark all objects again.Another option is to do: UnusedObjectDiscoverer analyse: aBlock where aBlock is what you want to analyze.Example:
UnusedObjectDiscoverer current startDiscovery.
Transcript show: 'Do something'.
Transcript browse.
UnusedObjectDiscoverer current stopDiscoveryAndGetStadistics inspect.
Or:
UnusedObjectDiscoverer analyse: [Transcript show: 'Do something'.]

Getting Results

Once you finished getting statistics you want to look at them. The first naive way is to just print the result of #stopDiscoveryAndGetStadistics which is a UnusedObjectStadistics instance. So for example if you print such object you get something like this:
Total amount of objects: 955887
Amount of used objects: 3804
Percentage of used objects: 0.397954988403441
Amount of unused objects: 952083
Percentage of unused objects: 99.60204501159656
Total bytes of memory used: 44408428
Bytes of memory for the used objects: 6617252
Percentage of memory for the used objects: 14.90089223604132
Bytes of memory for the unused objects: 37791176
Percentage of memory for the unused objects: 85.09910776395868

Visualizations

Of course, just analyzing the numbers of the statistics may not be enough in certain scenarios. For such purpose, we have developed special visualizations.


Abstract

It is important to understand which parts of the system are instantiated but also which are used or unused. We define that a used object is one that receives a message or that is directly used by the VirtualMachine, during a specific period of time.

The main challenge here is where to store the mark of each object. Adding an instance variable to Object (the root class of the Smalltalk hierarchy chain) and store there a Boolean object is not possible in Pharo, and the requirement of an extra reference for each object is highly memory consuming. Our solution modifies the Pharo VM so that we can use an empty bit of the object header to mark objects as used. That way we do not use extra memory and it works efficiently. We also modify the code of the VM that implements the message send to turn on the bit when an object receives a message.

Interesting Links

  • An already compiled Virutal Machine (for MacOS) for testing available here. Otherwise a new VM must be compiled from sources and our changes. Still need to document how to do this.
  • Slides of presentation in Smalltalks 2010. You can also download a pdf.

Installation

Take a Pharo image an evaluate:

Gofer new
	squeaksource: 'UsedObjects';
	package: 'ConfigurationOfUsedObjects';
load.
(Smalltalk at: #ConfigurationOfUsedObjects) project lastVersion load. 

Getting Started

The main class is called UnusedObjectDiscoverer and lets you find used objects during an execution. In order to do that:

1) You first have to evauate: UnusedObjectDiscoverer current startDiscovery. With that, you mark all objects as unused so that you can start a clean discovery.

2) Then, you do things. Run a seaside app, develope, code, etc.

3) Once you are finished and want to see the usage, print or inspect: UnusedObjectDiscoverer current stopDiscoveryAndGetStadistics This will get the statistics and unmark all objects again.

Another option is to do: UnusedObjectDiscoverer analyse: aBlock where aBlock is what you want to analyze.

Example:

UnusedObjectDiscoverer current startDiscovery.
Transcript show: 'Do something'.
Transcript browse.
UnusedObjectDiscoverer current stopDiscoveryAndGetStadistics inspect.

Or:

UnusedObjectDiscoverer analyse: [Transcript show: 'Do something'.]

Getting Results

Once you finished getting statistics you want to look at them. The first naive way is to just print the result of #stopDiscoveryAndGetStadistics which is a UnusedObjectStadistics instance. So for example if you print such object you get something like this:

Total amount of objects: 955887
Amount of used objects: 3804
Percentage of used objects: 0.397954988403441
Amount of unused objects: 952083
Percentage of unused objects: 99.60204501159656
Total bytes of memory used: 44408428
Bytes of memory for the used objects: 6617252
Percentage of memory for the used objects: 14.90089223604132
Bytes of memory for the unused objects: 37791176
Percentage of memory for the unused objects: 85.09910776395868

Visualizations

Of course, just analyzing the numbers of the statistics may not be enough in certain scenarios. For such purpose, we have developed special visualizations.