MemoryUsageView.st
changeset 52 7b48409ae088
parent 49 6fe62433cfa3
child 57 36e13831b62d
--- a/MemoryUsageView.st	Thu Nov 17 15:44:34 1994 +0100
+++ b/MemoryUsageView.st	Thu Nov 17 15:47:59 1994 +0100
@@ -42,7 +42,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libtool/MemoryUsageView.st,v 1.3 1994-10-28 03:30:32 claus Exp $
+$Header: /cvs/stx/stx/libtool/MemoryUsageView.st,v 1.4 1994-11-17 14:46:57 claus Exp $
 "
 !
 
@@ -90,7 +90,88 @@
 	(className startsWith:'<') ifFalse:[
 	    (className startsWith:'all') ifFalse:[
 		class := Smalltalk at:className asSymbol.
-		class allInstances inspect
+		self withCursor:(Cursor questionMark) do:[
+		    |insts|
+
+		    insts := class allInstances.
+		    insts size > 500 ifTrue:[
+			(self confirm:'there are ' , insts size printString , ' instances.\\Do you really want to see them all ?' withCRs)
+			ifFalse:[^ self]
+		    ].
+		    insts inspect
+		]
+	    ]
+	]
+    ]
+!
+
+inspectOwners
+    |line className class|
+
+    line := list selectionValue.
+    (line notNil and:[line notEmpty]) ifTrue:[
+	className := line asCollectionOfWords first.
+	"
+	 special kludge
+	"
+	(className startsWith:'<') ifFalse:[
+	    (className startsWith:'all') ifFalse:[
+		class := Smalltalk at:className asSymbol.
+		self withCursor:(Cursor questionMark) do:[
+		    |owners dict|
+
+		    owners := (ObjectMemory whoReferencesInstancesOf:class).
+		    owners isNil ifTrue:[
+			self information:'no owners found - next GC should remove it'.
+			^ self
+		    ].
+		    owners := owners asOrderedCollection.
+		    owners size > 500 ifTrue:[
+			(self confirm:'there are ' , owners size printString , ' owners.\\Do you really want to see them all ?' withCRs)
+			ifFalse:[^ self]
+		    ].
+		    dict := IdentityDictionary new.
+		    owners do:[:owner |
+			|set names oClass s|
+
+			"
+			 skip weakArrays ... (they dont count)
+			"
+			(owner isMemberOf:WeakArray) ifFalse:[
+			    set := Set new.
+			    names := owner class allInstVarNames.
+			    oClass := owner class.
+			    1 to:oClass instSize do:[:i |
+				((owner instVarAt:i) isMemberOf:class) ifTrue:[
+				    set add:(names at:i).
+				].
+			    ].
+			    oClass isVariable ifTrue:[
+				oClass isPointers ifTrue:[
+				    1 to:owner basicSize do:[:i |
+					((owner basicAt:i) isMemberOf:class) ifTrue:[
+					    set add:i
+					]
+				    ]
+				]
+			    ].
+			    "
+			     put a describing string into the dictionary
+			    "
+			    s := 'references in: '.
+			    set do:[:name | 
+					name isString ifTrue:[
+					    s := s , name , ' '
+					] ifFalse:[
+					    s := s , '[' , name printString , '] '
+					]
+				   ].
+			    dict at:owner put:s.
+"/                            dict at:owner put:set
+			]
+		    ].
+		    dict inspect
+		]
 	    ]
 	]
     ]
@@ -114,14 +195,15 @@
 updateDisplay
     "update the displayed list"
 
-    |classNames counts sumSizes percents avgSizes rawData l line allMemory overAllCount overAllAvgSize|
-
     windowGroup withCursor:Cursor wait do:[
+	|classNames counts sumSizes percents avgSizes rawData 
+	 l line allMemory overAllCount overAllAvgSize|
 
 	rawData := info asSortedCollection:sortBlock.
 
 "/        "this avoids getting a sorted collection in the collect: below"
 "/        rawData := rawData asArray.
+"/ collect: has been fixed ...
 
 	classNames := rawData collect:[:i | 
 	    |cls|
@@ -141,11 +223,13 @@
 	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].
+	percents := sumSizes collect:[:sz | (sz asFloat / allMemory * 1000) 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|
+
 	    line := (classNames at:i) printStringPaddedTo:30 with:Character space.
 	    line := line , ((counts at:i) printStringLeftPaddedTo:10).
 	    line := line , ((avgSizes at:i) printStringLeftPaddedTo:10).
@@ -173,11 +257,8 @@
 updateInfo
     "scan all memory and collect the information"
 
-    |myProcess myPriority|
-
     windowGroup withCursor:Cursor questionMark do:[
-
-	info := IdentityDictionary new:600.
+	|myProcess myPriority|
 
 	"find all objects, collect stuff in info"
 
@@ -188,6 +269,8 @@
 	myPriority := myProcess priority.
 	myProcess priority:(Processor userBackgroundPriority).
 
+	info := IdentityDictionary new:600.
+
 	[
 	    ObjectMemory allObjectsDo:[:o |
 		|i class|
@@ -201,12 +284,11 @@
 		] 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 := info at:class ifAbsent:[].
+		i isNil ifTrue:[
+		    i := Array with:class with:1 with:(ObjectMemory sizeOf:o).
+		    info at:class put:i.
+		] ifFalse:[
 		    i at:2 put:((i at:2) + 1).
 		    i at:3 put:((i at:3) + (ObjectMemory sizeOf:o))
 		]
@@ -238,10 +320,13 @@
     helpView := ScrollableView for:SelectionInListView in:self.
     helpView origin:(0.0 @ l height) corner:1.0 @ 1.0.
 
-    l origin:(helpView scrollBar width @ 0.0).
+    list := helpView scrolledView.
+
+    l origin:(list originRelativeTo:self) x @ 0.0.
 
-    list := helpView scrolledView.
     list font:(self font).
+    l font:(self font).
+
     list middleButtonMenu:(PopUpMenu
 				labels:(
 					resources array:#(
@@ -250,6 +335,7 @@
 					    'sort by memory usage'
 					    '-'
 					    'inspect instances'
+					    'owners'
 					    '-'
 					    'update'
 					))
@@ -259,12 +345,15 @@
 					 sortByMemoryUsage
 					 nil
 					 inspectInstances
+					 inspectOwners
 					 nil
 					 update
 					)
 				receiver:self
 				     for:list).
 
-    "MemoryUsageView start"
+    "
+     MemoryUsageView open
+    "
 ! !