MemoryUsageView.st
author claus
Sat, 08 Jan 1994 18:39:17 +0100
changeset 19 4cde336c0794
child 45 950b84ba89e6
permissions -rw-r--r--
Initial revision

StandardSystemView subclass:#MemoryUsageView
         instanceVariableNames:'info list sortBlock'
         classVariableNames:''
         poolDictionaries:''
         category:'Interface-Debugger'
!

!MemoryUsageView methodsFor:'realization'!

realize
    super realize.
    self updateInfo.
    self sortByClass.
! !

!MemoryUsageView methodsFor:'initialization'!

initialize
    |l helpView headLine|

    super initialize.
    self label:'Memory usage'.

    headLine := 'class                           # of insts  avg sz     bytes   %mem'.

    l := Label in:self.
    l origin:(0.0 @ 0.0) corner:(1.0 @ l height).
    l borderWidth:0.
    l label:headLine.
    l adjust:#left.

    self extent:((font widthOf:headLine) + (device horizontalPixelPerMillimeter * 15) rounded) @ self height.

    helpView := ScrollableView for:ListView in:self.
    helpView origin:(0.0 @ l height)
             extent:[width @ (height - l height - l margin)].

    l origin:(helpView scrollBar width @ 0.0).

    list := helpView scrolledView.
    list origin:(0.0 @ 0.0) extent:(1.0 @ 1.0).

    list middleButtonMenu:(PopUpMenu
                                labels:#(
                                         'by class'
                                         'by inst count'
                                         'by memory usage'
                                         '-'
                                         'update'
                                        )

                             selectors:#(sortByClass
                                         sortByInstCount
                                         sortByMemoryUsage
                                         nil
                                         update
                                        )
                                receiver:self
                                     for:list).

    "MemoryUsageView start"
! !

!MemoryUsageView methodsFor:'menu actions'!

sortByClass
    self label:'Memory usage; by class'.
    sortBlock := [:a :b | (a at:1) name < (b at:1) name].
    self updateDisplay
!

sortByInstCount
    self label:'Memory usage; by instance count'.
    sortBlock := [:a :b | (a at:2) > (b at:2) ].
    self updateDisplay
!

sortByMemoryUsage
    self label:'Memory usage; by memory usage'.
    sortBlock := [:a :b | (a at:3) > (b at:3)].
    self updateDisplay
!

update
    self updateInfo.
    self updateDisplay
! !

!MemoryUsageView methodsFor:'private'!

updateInfo
    self cursor:Cursor wait.
    list cursor:Cursor wait.

    info := IdentityDictionary new:600.

    "find all objects, collect stuff in info"

    ObjectMemory allObjectsDo:[:o |
        |i class|

        o isBehavior ifTrue:[
            o isMeta ifTrue:[
                class := Metaclass
            ] ifFalse:[
                class := Class
            ]
        ] ifFalse:[
            class := o class.
        ].
        (info includesKey:class) ifFalse:[
            info at:class put:(Array with:class 
                                     with:1 
                                     with:(ObjectMemory sizeOf:o))
        ] ifTrue:[
            i := info at:class.
            i at:2 put:((i at:2) + 1).
            i at:3 put:((i at:3) + (ObjectMemory sizeOf:o))
        ]
    ].

    self cursor:Cursor normal.
    list cursor:Cursor normal.
! 

updateDisplay
    |classNames counts sumSizes percents avgSizes rawData l line allMemory overAllCount overAllAvgSize|

    self cursor:Cursor wait.
    list cursor:Cursor wait.

    rawData := info asSortedCollection:sortBlock.

    "this avoids getting a sorted collection in the collect: below"
    rawData := rawData asArray.

    classNames := rawData collect:[:i | 
        |cls|

        cls := i at:1.
        cls == Class ifTrue:[
            '<all classes>'
        ] ifFalse:[
            cls == Metaclass ifTrue:[
                '<all metaclasses>'
            ] ifFalse:[
                cls name
            ] 
        ] 
    ].

    counts := rawData collect:[:i | (i at:2) ].
    sumSizes := rawData collect:[:i | (i at:3) ].
    allMemory := ObjectMemory bytesUsed.
    percents := sumSizes collect:[:sz | (sz / allMemory * 100 * 10) rounded / 10.0].
    avgSizes := (1 to:sumSizes size) collect:[:i | (((sumSizes at:i) / (counts at:i)) * 10) rounded / 10.0].

    l := OrderedCollection new.
    1 to:classNames size do:[:i |
        line := (classNames at:i) printStringPaddedTo:30 with:Character space.
        line := line , ((counts at:i) printStringLeftPaddedTo:10).
        line := line , ((avgSizes at:i) printStringLeftPaddedTo:10).
        line := line , ((sumSizes at:i) printStringLeftPaddedTo:10).
        line := line , ((percents at:i) printStringLeftPaddedTo:7).
        l add:line
    ].

    "add summary line"
    overAllCount := counts inject:0 into:[:sum :this | sum + this].
    overAllAvgSize := ((allMemory / overAllCount) * 10) rounded / 10.0.

    l add:''.
    line := 'all objects' printStringPaddedTo:30 with:Character space.
    line := line , (overAllCount printStringLeftPaddedTo:10).
    line := line , (overAllAvgSize printStringLeftPaddedTo:10).
    line := line , (allMemory printStringLeftPaddedTo:10).
    line := line , (100.0 printStringLeftPaddedTo:7).
    l add:line.

    list list:l.

    self cursor:Cursor normal.
    list cursor:Cursor normal.
! !