88 special kludge |
88 special kludge |
89 " |
89 " |
90 (className startsWith:'<') ifFalse:[ |
90 (className startsWith:'<') ifFalse:[ |
91 (className startsWith:'all') ifFalse:[ |
91 (className startsWith:'all') ifFalse:[ |
92 class := Smalltalk at:className asSymbol. |
92 class := Smalltalk at:className asSymbol. |
93 class allInstances inspect |
93 self withCursor:(Cursor questionMark) do:[ |
|
94 |insts| |
|
95 |
|
96 insts := class allInstances. |
|
97 insts size > 500 ifTrue:[ |
|
98 (self confirm:'there are ' , insts size printString , ' instances.\\Do you really want to see them all ?' withCRs) |
|
99 ifFalse:[^ self] |
|
100 ]. |
|
101 insts inspect |
|
102 ] |
|
103 ] |
|
104 ] |
|
105 ] |
|
106 ! |
|
107 |
|
108 inspectOwners |
|
109 |line className class| |
|
110 |
|
111 line := list selectionValue. |
|
112 (line notNil and:[line notEmpty]) ifTrue:[ |
|
113 className := line asCollectionOfWords first. |
|
114 " |
|
115 special kludge |
|
116 " |
|
117 (className startsWith:'<') ifFalse:[ |
|
118 (className startsWith:'all') ifFalse:[ |
|
119 class := Smalltalk at:className asSymbol. |
|
120 self withCursor:(Cursor questionMark) do:[ |
|
121 |owners dict| |
|
122 |
|
123 owners := (ObjectMemory whoReferencesInstancesOf:class). |
|
124 owners isNil ifTrue:[ |
|
125 self information:'no owners found - next GC should remove it'. |
|
126 ^ self |
|
127 ]. |
|
128 owners := owners asOrderedCollection. |
|
129 owners size > 500 ifTrue:[ |
|
130 (self confirm:'there are ' , owners size printString , ' owners.\\Do you really want to see them all ?' withCRs) |
|
131 ifFalse:[^ self] |
|
132 ]. |
|
133 dict := IdentityDictionary new. |
|
134 owners do:[:owner | |
|
135 |set names oClass s| |
|
136 |
|
137 " |
|
138 skip weakArrays ... (they dont count) |
|
139 " |
|
140 (owner isMemberOf:WeakArray) ifFalse:[ |
|
141 set := Set new. |
|
142 names := owner class allInstVarNames. |
|
143 oClass := owner class. |
|
144 1 to:oClass instSize do:[:i | |
|
145 ((owner instVarAt:i) isMemberOf:class) ifTrue:[ |
|
146 set add:(names at:i). |
|
147 ]. |
|
148 ]. |
|
149 oClass isVariable ifTrue:[ |
|
150 oClass isPointers ifTrue:[ |
|
151 1 to:owner basicSize do:[:i | |
|
152 ((owner basicAt:i) isMemberOf:class) ifTrue:[ |
|
153 set add:i |
|
154 ] |
|
155 ] |
|
156 ] |
|
157 ]. |
|
158 " |
|
159 put a describing string into the dictionary |
|
160 " |
|
161 s := 'references in: '. |
|
162 set do:[:name | |
|
163 name isString ifTrue:[ |
|
164 s := s , name , ' ' |
|
165 ] ifFalse:[ |
|
166 s := s , '[' , name printString , '] ' |
|
167 ] |
|
168 ]. |
|
169 dict at:owner put:s. |
|
170 "/ dict at:owner put:set |
|
171 ] |
|
172 ]. |
|
173 dict inspect |
|
174 ] |
94 ] |
175 ] |
95 ] |
176 ] |
96 ] |
177 ] |
97 ! |
178 ! |
98 |
179 |
112 !MemoryUsageView methodsFor:'private'! |
193 !MemoryUsageView methodsFor:'private'! |
113 |
194 |
114 updateDisplay |
195 updateDisplay |
115 "update the displayed list" |
196 "update the displayed list" |
116 |
197 |
117 |classNames counts sumSizes percents avgSizes rawData l line allMemory overAllCount overAllAvgSize| |
|
118 |
|
119 windowGroup withCursor:Cursor wait do:[ |
198 windowGroup withCursor:Cursor wait do:[ |
|
199 |classNames counts sumSizes percents avgSizes rawData |
|
200 l line allMemory overAllCount overAllAvgSize| |
120 |
201 |
121 rawData := info asSortedCollection:sortBlock. |
202 rawData := info asSortedCollection:sortBlock. |
122 |
203 |
123 "/ "this avoids getting a sorted collection in the collect: below" |
204 "/ "this avoids getting a sorted collection in the collect: below" |
124 "/ rawData := rawData asArray. |
205 "/ rawData := rawData asArray. |
|
206 "/ collect: has been fixed ... |
125 |
207 |
126 classNames := rawData collect:[:i | |
208 classNames := rawData collect:[:i | |
127 |cls| |
209 |cls| |
128 |
210 |
129 cls := i at:1. |
211 cls := i at:1. |
139 ]. |
221 ]. |
140 |
222 |
141 counts := rawData collect:[:i | (i at:2) ]. |
223 counts := rawData collect:[:i | (i at:2) ]. |
142 sumSizes := rawData collect:[:i | (i at:3) ]. |
224 sumSizes := rawData collect:[:i | (i at:3) ]. |
143 allMemory := ObjectMemory bytesUsed. |
225 allMemory := ObjectMemory bytesUsed. |
144 percents := sumSizes collect:[:sz | (sz / allMemory * 100 * 10) rounded / 10.0]. |
226 percents := sumSizes collect:[:sz | (sz asFloat / allMemory * 1000) rounded / 10.0]. |
145 avgSizes := (1 to:sumSizes size) collect:[:i | (((sumSizes at:i) / (counts at:i)) * 10) rounded / 10.0]. |
227 avgSizes := (1 to:sumSizes size) collect:[:i | (((sumSizes at:i) / (counts at:i)) * 10) rounded / 10.0]. |
146 |
228 |
147 l := OrderedCollection new. |
229 l := OrderedCollection new. |
148 1 to:classNames size do:[:i | |
230 1 to:classNames size do:[:i | |
|
231 |line| |
|
232 |
149 line := (classNames at:i) printStringPaddedTo:30 with:Character space. |
233 line := (classNames at:i) printStringPaddedTo:30 with:Character space. |
150 line := line , ((counts at:i) printStringLeftPaddedTo:10). |
234 line := line , ((counts at:i) printStringLeftPaddedTo:10). |
151 line := line , ((avgSizes at:i) printStringLeftPaddedTo:10). |
235 line := line , ((avgSizes at:i) printStringLeftPaddedTo:10). |
152 line := line , ((sumSizes at:i) printStringLeftPaddedTo:10). |
236 line := line , ((sumSizes at:i) printStringLeftPaddedTo:10). |
153 line := line , ((percents at:i) printStringLeftPaddedTo:7). |
237 line := line , ((percents at:i) printStringLeftPaddedTo:7). |
171 ! |
255 ! |
172 |
256 |
173 updateInfo |
257 updateInfo |
174 "scan all memory and collect the information" |
258 "scan all memory and collect the information" |
175 |
259 |
176 |myProcess myPriority| |
|
177 |
|
178 windowGroup withCursor:Cursor questionMark do:[ |
260 windowGroup withCursor:Cursor questionMark do:[ |
179 |
261 |myProcess myPriority| |
180 info := IdentityDictionary new:600. |
|
181 |
262 |
182 "find all objects, collect stuff in info" |
263 "find all objects, collect stuff in info" |
183 |
264 |
184 " |
265 " |
185 this is a time consuming operation; therefore lower my priority ... |
266 this is a time consuming operation; therefore lower my priority ... |
186 " |
267 " |
187 myProcess := Processor activeProcess. |
268 myProcess := Processor activeProcess. |
188 myPriority := myProcess priority. |
269 myPriority := myProcess priority. |
189 myProcess priority:(Processor userBackgroundPriority). |
270 myProcess priority:(Processor userBackgroundPriority). |
|
271 |
|
272 info := IdentityDictionary new:600. |
190 |
273 |
191 [ |
274 [ |
192 ObjectMemory allObjectsDo:[:o | |
275 ObjectMemory allObjectsDo:[:o | |
193 |i class| |
276 |i class| |
194 |
277 |
199 class := Class |
282 class := Class |
200 ] |
283 ] |
201 ] ifFalse:[ |
284 ] ifFalse:[ |
202 class := o class. |
285 class := o class. |
203 ]. |
286 ]. |
204 (info includesKey:class) ifFalse:[ |
287 i := info at:class ifAbsent:[]. |
205 info at:class put:(Array with:class |
288 i isNil ifTrue:[ |
206 with:1 |
289 i := Array with:class with:1 with:(ObjectMemory sizeOf:o). |
207 with:(ObjectMemory sizeOf:o)) |
290 info at:class put:i. |
208 ] ifTrue:[ |
291 ] ifFalse:[ |
209 i := info at:class. |
|
210 i at:2 put:((i at:2) + 1). |
292 i at:2 put:((i at:2) + 1). |
211 i at:3 put:((i at:3) + (ObjectMemory sizeOf:o)) |
293 i at:3 put:((i at:3) + (ObjectMemory sizeOf:o)) |
212 ] |
294 ] |
213 ]. |
295 ]. |
214 ] valueNowOrOnUnwindDo:[ |
296 ] valueNowOrOnUnwindDo:[ |
236 self extent:((font widthOf:headLine) + (device horizontalPixelPerMillimeter * 15) rounded) @ self height. |
318 self extent:((font widthOf:headLine) + (device horizontalPixelPerMillimeter * 15) rounded) @ self height. |
237 |
319 |
238 helpView := ScrollableView for:SelectionInListView in:self. |
320 helpView := ScrollableView for:SelectionInListView in:self. |
239 helpView origin:(0.0 @ l height) corner:1.0 @ 1.0. |
321 helpView origin:(0.0 @ l height) corner:1.0 @ 1.0. |
240 |
322 |
241 l origin:(helpView scrollBar width @ 0.0). |
|
242 |
|
243 list := helpView scrolledView. |
323 list := helpView scrolledView. |
|
324 |
|
325 l origin:(list originRelativeTo:self) x @ 0.0. |
|
326 |
244 list font:(self font). |
327 list font:(self font). |
|
328 l font:(self font). |
|
329 |
245 list middleButtonMenu:(PopUpMenu |
330 list middleButtonMenu:(PopUpMenu |
246 labels:( |
331 labels:( |
247 resources array:#( |
332 resources array:#( |
248 'sort by class' |
333 'sort by class' |
249 'sort by inst count' |
334 'sort by inst count' |
250 'sort by memory usage' |
335 'sort by memory usage' |
251 '-' |
336 '-' |
252 'inspect instances' |
337 'inspect instances' |
|
338 'owners' |
253 '-' |
339 '-' |
254 'update' |
340 'update' |
255 )) |
341 )) |
256 |
342 |
257 selectors:#(sortByClass |
343 selectors:#(sortByClass |
258 sortByInstCount |
344 sortByInstCount |
259 sortByMemoryUsage |
345 sortByMemoryUsage |
260 nil |
346 nil |
261 inspectInstances |
347 inspectInstances |
|
348 inspectOwners |
262 nil |
349 nil |
263 update |
350 update |
264 ) |
351 ) |
265 receiver:self |
352 receiver:self |
266 for:list). |
353 for:list). |
267 |
354 |
268 "MemoryUsageView start" |
355 " |
269 ! ! |
356 MemoryUsageView open |
270 |
357 " |
|
358 ! ! |
|
359 |