16 */ |
16 */ |
17 |
17 |
18 package com.nokia.carbide.cpp.pi.memory; |
18 package com.nokia.carbide.cpp.pi.memory; |
19 |
19 |
20 import java.util.ArrayList; |
20 import java.util.ArrayList; |
|
21 import java.util.Arrays; |
21 import java.util.Enumeration; |
22 import java.util.Enumeration; |
22 import java.util.HashSet; |
23 import java.util.HashSet; |
23 import java.util.Hashtable; |
24 import java.util.Hashtable; |
24 import java.util.Iterator; |
25 import java.util.Iterator; |
25 import java.util.SortedMap; |
26 import java.util.SortedMap; |
26 import java.util.TreeMap; |
27 import java.util.TreeMap; |
27 import java.util.Map.Entry; |
|
28 |
|
29 import org.eclipse.draw2d.IFigure; |
|
30 |
28 |
31 import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository; |
29 import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository; |
32 import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace; |
30 import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace; |
33 import com.nokia.carbide.cpp.internal.pi.model.GenericThread; |
31 import com.nokia.carbide.cpp.internal.pi.model.GenericThread; |
34 import com.nokia.carbide.cpp.internal.pi.model.TraceWithThreads; |
32 import com.nokia.carbide.cpp.internal.pi.model.TraceWithThreads; |
63 transient private int intervalMaxTotal = 0; |
61 transient private int intervalMaxTotal = 0; |
64 |
62 |
65 transient private Hashtable<String, TreeMap<Long, MemSample>> drawDataByMemThread = null; |
63 transient private Hashtable<String, TreeMap<Long, MemSample>> drawDataByMemThread = null; |
66 transient private ArrayList<MemSampleByTime> drawDataByTime; |
64 transient private ArrayList<MemSampleByTime> drawDataByTime; |
67 transient private HashSet<MemThread> noDuplicateMemThreads; |
65 transient private HashSet<MemThread> noDuplicateMemThreads; |
68 |
66 |
|
67 transient private Hashtable<String, ProfiledLibraryEvent> drawDataByLibraryEvent = null; |
|
68 transient private TreeMap<Long, ArrayList<MemSample>> drawLibraryEventDataByTime = null; |
|
69 |
|
70 transient private LibraryEventColorPalette libraryEventColorPalette = null; |
69 transient private long intervalStart = -1; |
71 transient private long intervalStart = -1; |
70 transient private long intervalEnd = -1; |
72 transient private long intervalEnd = -1; |
|
73 |
|
74 |
71 |
75 |
72 private int version; |
76 private int version; |
73 |
77 |
74 public MemTrace() { |
78 public MemTrace() { |
75 firstSynchTimes = new Hashtable<Integer, Integer>(); |
79 firstSynchTimes = new Hashtable<Integer, Integer>(); |
76 lastSynchTimes = new Hashtable<Integer, Integer>(); |
80 lastSynchTimes = new Hashtable<Integer, Integer>(); |
77 } |
|
78 |
|
79 public void addSample(MemSample sample) { |
|
80 this.samples.add(sample); |
|
81 } |
81 } |
82 |
82 |
83 public MemSample getMemSample(int number) { |
83 public MemSample getMemSample(int number) { |
84 return (MemSample) this.samples.elementAt(number); |
84 return (MemSample) this.samples.elementAt(number); |
85 } |
85 } |
204 // the first sample in each time period contains system-wide |
204 // the first sample in each time period contains system-wide |
205 // info |
205 // info |
206 if (memSample.thread.threadId == 0xffffffffbabbeaaaL) { |
206 if (memSample.thread.threadId == 0xffffffffbabbeaaaL) { |
207 usedMemory = memSample.heapSize; |
207 usedMemory = memSample.heapSize; |
208 freeMemory = memSample.stackSize; |
208 freeMemory = memSample.stackSize; |
209 memSample = (MemSample) e.nextElement(); |
209 if(e.hasMoreElements()){ |
|
210 memSample = (MemSample) e.nextElement(); |
|
211 } |
|
212 else{ |
|
213 break; |
|
214 } |
210 } |
215 } |
211 |
216 |
212 // the 2nd sample in each time period has memory model and |
217 // the 2nd sample in each time period has memory model and |
213 // CodeSeg data |
218 // CodeSeg data |
214 if (memSample.thread.threadId == 0xffffffffbabbea20L) { |
219 if (memSample.thread.threadId == 0xffffffffbabbea20L) { |
215 usedMemory = memSample.heapSize; |
220 usedMemory = memSample.heapSize; |
216 freeMemory = memSample.stackSize; |
221 freeMemory = memSample.stackSize; |
217 memSample = (MemSample) e.nextElement(); |
222 if(e.hasMoreElements()){ |
|
223 memSample = (MemSample) e.nextElement(); |
|
224 } |
|
225 else{ |
|
226 break; |
|
227 } |
|
228 |
218 } |
229 } |
219 |
230 |
220 // Create MemSampleByTime object based on sample |
231 // Create MemSampleByTime object based on sample |
221 MemSampleByTime memSampleByTime = new MemSampleByTime( |
232 MemSampleByTime memSampleByTime = new MemSampleByTime( |
222 memSample.sampleSynchTime, usedMemory + freeMemory, |
233 memSample.sampleSynchTime, usedMemory + freeMemory, |
267 } |
278 } |
268 |
279 |
269 public void gatherEventBasedDrawData() { |
280 public void gatherEventBasedDrawData() { |
270 if (drawDataByMemThread != null) |
281 if (drawDataByMemThread != null) |
271 return; // already initialised |
282 return; // already initialised |
272 |
|
273 drawDataByMemThread = new Hashtable<String, TreeMap<Long, MemSample>>(); |
283 drawDataByMemThread = new Hashtable<String, TreeMap<Long, MemSample>>(); |
|
284 if(version >= 203){ |
|
285 drawDataByLibraryEvent = new Hashtable<String, ProfiledLibraryEvent>(); |
|
286 } |
|
287 |
274 memoryModel = MemTrace.MEMORY_UNKNOWN; |
288 memoryModel = MemTrace.MEMORY_UNKNOWN; |
275 getThreadsFromTrace(); |
289 getThreadsFromTrace(); |
276 |
290 |
277 if (drawDataByTime == null) |
291 if (drawDataByTime == null) |
278 drawDataByTime = new ArrayList<MemSampleByTime>(); |
292 drawDataByTime = new ArrayList<MemSampleByTime>(); |
293 // info |
307 // info |
294 if (memSample.thread.threadId == 0xffffffffbabbeaaaL) { |
308 if (memSample.thread.threadId == 0xffffffffbabbeaaaL) { |
295 usedMemory = memSample.heapSize; |
309 usedMemory = memSample.heapSize; |
296 freeMemory = memSample.stackSize; |
310 freeMemory = memSample.stackSize; |
297 addSampleToThread(memSample); |
311 addSampleToThread(memSample); |
298 memSample = (MemSample) e.nextElement(); |
312 if(e.hasMoreElements()){ |
|
313 memSample = (MemSample) e.nextElement(); |
|
314 } |
|
315 else{ |
|
316 break; |
|
317 } |
299 |
318 |
300 } |
319 } |
301 |
320 |
302 // Create MemSampleByTime object based on sample |
321 // Create MemSampleByTime object based on sample |
303 // MemSampleByTime memSampleByTime = new |
322 // MemSampleByTime memSampleByTime = new |
324 |
343 |
325 } |
344 } |
326 |
345 |
327 private void addSampleToThread(MemSample sample) { |
346 private void addSampleToThread(MemSample sample) { |
328 |
347 |
|
348 if (version >= 203) { |
|
349 String library = getLibraryNameString(sample.thread.fullName); |
|
350 if (library != null) { |
|
351 ProfiledLibraryEvent ple = drawDataByLibraryEvent.get(library); |
|
352 if (ple != null) { |
|
353 // Add initial sample to library event |
|
354 ple.addMemSample(sample); |
|
355 return; |
|
356 } |
|
357 } |
|
358 |
|
359 } |
329 // get sample array from thread |
360 // get sample array from thread |
330 TreeMap<Long, MemSample> samples = drawDataByMemThread |
361 TreeMap<Long, MemSample> samples = drawDataByMemThread |
331 .get(sample.thread.fullName); |
362 .get(sample.thread.fullName); |
332 |
363 |
333 if (sample.type == MemTraceParser.SAMPLE_CODE_DELETE_CHUNK) { |
364 if (sample.type == MemTraceParser.SAMPLE_CODE_DELETE_CHUNK) { |
353 // the parser creates multiple copies of the same MemThread item, |
384 // the parser creates multiple copies of the same MemThread item, |
354 // so we have to use the full name of the MemThread to access sample |
385 // so we have to use the full name of the MemThread to access sample |
355 // data |
386 // data |
356 for (MemThread memThread : threads) { |
387 for (MemThread memThread : threads) { |
357 String processedThreadName = memThread.threadName; |
388 String processedThreadName = memThread.threadName; |
358 |
389 boolean libraryEvent = false; |
359 // Add Thread ID into processedThreadName |
390 // Add Thread ID into processedThreadName |
360 // looking for _T and _C suffixes and remove them for thread |
391 // looking for _T and _C suffixes and remove them for thread |
361 if (processedThreadName.endsWith("_T")) //$NON-NLS-1$ |
392 if (processedThreadName.endsWith("_T")) //$NON-NLS-1$ |
362 { |
393 { |
363 processedThreadName = processedThreadName.substring(0, |
394 processedThreadName = processedThreadName.substring(0, |
365 + "_" + memThread.threadId; //$NON-NLS-1$ |
396 + "_" + memThread.threadId; //$NON-NLS-1$ |
366 } else if (processedThreadName.endsWith("_C")) { //$NON-NLS-1$ |
397 } else if (processedThreadName.endsWith("_C")) { //$NON-NLS-1$ |
367 processedThreadName = processedThreadName.substring(0, |
398 processedThreadName = processedThreadName.substring(0, |
368 processedThreadName.length() - 2) |
399 processedThreadName.length() - 2) |
369 + " [0x" + Integer.toHexString(memThread.threadId) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
400 + " [0x" + Integer.toHexString(memThread.threadId) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
370 } else { |
401 } else if (processedThreadName.endsWith("_L")) { //$NON-NLS-1$ |
|
402 processedThreadName = processedThreadName.substring(0, |
|
403 processedThreadName.length() - 2) |
|
404 + " [0x" + Integer.toHexString(memThread.threadId) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
|
405 libraryEvent = true; |
|
406 }else { |
371 processedThreadName += "_" + memThread.threadId; //$NON-NLS-1$ |
407 processedThreadName += "_" + memThread.threadId; //$NON-NLS-1$ |
372 } |
408 } |
373 |
409 |
374 // Full name contains process name, thread name and thread id |
410 // Full name contains process name, thread name and thread id |
375 memThread.fullName = memThread.processName |
411 memThread.fullName = memThread.processName |
383 memThread.maxMemoryItem = new MaxMemoryItem(); |
419 memThread.maxMemoryItem = new MaxMemoryItem(); |
384 memThread.maxMemoryItem.maxChunks = 0; |
420 memThread.maxMemoryItem.maxChunks = 0; |
385 memThread.maxMemoryItem.maxStackHeap = 0; |
421 memThread.maxMemoryItem.maxStackHeap = 0; |
386 memThread.maxMemoryItem.maxTotal = 0; |
422 memThread.maxMemoryItem.maxTotal = 0; |
387 |
423 |
388 if (drawDataByMemThread.get(memThread.fullName) == null) { |
424 if (libraryEvent) { |
389 drawDataByMemThread.put(memThread.fullName, |
425 String name = getLibraryNameString(memThread.fullName); |
390 new TreeMap<Long, MemSample>()); |
426 if (drawDataByLibraryEvent.get(name) == null) { |
391 noDuplicateMemThreads.add(memThread); |
427 ProfiledLibraryEvent ple = new ProfiledLibraryEvent(name); |
|
428 ple.setColor(getLibraryEventColorPalette().getColor(name)); |
|
429 drawDataByLibraryEvent.put(name, ple); |
|
430 } |
|
431 } else { |
|
432 if (drawDataByMemThread.get(memThread.fullName) == null) { |
|
433 drawDataByMemThread.put(memThread.fullName, |
|
434 new TreeMap<Long, MemSample>()); |
|
435 noDuplicateMemThreads.add(memThread); |
|
436 } |
392 } |
437 } |
393 } |
438 } |
394 |
439 |
395 } |
440 } |
396 |
441 |
397 public TreeMap<Long, MemSample> getDrawDataByMemThread(MemThread id) { |
442 public TreeMap<Long, MemSample> getDrawDataByMemThread(MemThread id) { |
398 return this.drawDataByMemThread.get(id.fullName); |
443 return this.drawDataByMemThread.get(id.fullName); |
399 } |
444 } |
|
445 |
|
446 public Hashtable<String, TreeMap<Long, MemSample>> getDrawDataByMemThread() { |
|
447 return this.drawDataByMemThread; |
|
448 } |
400 |
449 |
401 public ArrayList<MemSampleByTime> getDrawDataByTime() { |
450 public ArrayList<MemSampleByTime> getDrawDataByTime() { |
|
451 if (drawDataByTime.isEmpty() && getVersion() >= 202) { |
|
452 TreeMap<Long, MemSample> events = drawDataByMemThread |
|
453 .get("TOTAL_MEMORY::TOTAL_MEMORY_-1162089814"); //$NON-NLS-1$ |
|
454 |
|
455 Iterator<MemSample> iterator = events.values().iterator(); |
|
456 while (iterator.hasNext()) { |
|
457 MemSample memSample = iterator.next(); |
|
458 drawDataByTime.add(new MemSampleByTime( |
|
459 memSample.sampleSynchTime, memSample.stackSize |
|
460 + memSample.heapSize, memSample.heapSize)); |
|
461 } |
|
462 } |
402 return this.drawDataByTime; |
463 return this.drawDataByTime; |
403 } |
464 } |
404 |
465 |
405 public HashSet<MemThread> getNoDuplicateMemThreads() { |
466 public HashSet<MemThread> getNoDuplicateMemThreads() { |
406 return this.noDuplicateMemThreads; |
467 return this.noDuplicateMemThreads; |
432 || ((startTime == intervalStart) && (endTime == intervalEnd))) |
493 || ((startTime == intervalStart) && (endTime == intervalEnd))) |
433 return item; |
494 return item; |
434 |
495 |
435 if (this.getVersion() >= 202) { |
496 if (this.getVersion() >= 202) { |
436 TreeMap<Long, MemSample> events = drawDataByMemThread |
497 TreeMap<Long, MemSample> events = drawDataByMemThread |
437 .get("TOTAL_MEMORY::TOTAL_MEMORY_-1162089814"); |
498 .get("TOTAL_MEMORY::TOTAL_MEMORY_-1162089814"); //$NON-NLS-1$ |
438 |
499 |
439 Iterator<MemSample> values = events.values().iterator(); |
500 Iterator<MemSample> values = events.values().iterator(); |
440 |
501 |
441 while (values.hasNext()) { |
502 while (values.hasNext()) { |
442 MemSample memSample = values.next(); |
503 MemSample memSample = values.next(); |
650 } catch (Exception e) { |
721 } catch (Exception e) { |
651 return null; |
722 return null; |
652 } |
723 } |
653 |
724 |
654 } |
725 } |
|
726 |
|
727 public Hashtable<String, ProfiledLibraryEvent> getLibraryEvents(){ |
|
728 return drawDataByLibraryEvent; |
|
729 } |
|
730 |
|
731 public LibraryEventColorPalette getLibraryEventColorPalette(){ |
|
732 if(libraryEventColorPalette == null){ |
|
733 libraryEventColorPalette = new LibraryEventColorPalette(); |
|
734 } |
|
735 return libraryEventColorPalette; |
|
736 } |
|
737 |
|
738 |
|
739 public ArrayList<MemSample> getLibraryEventDataByTime(int graphIndex, long time, long scale) { |
|
740 if(drawLibraryEventDataByTime == null){ |
|
741 // find library events by time |
|
742 drawLibraryEventDataByTime = new TreeMap<Long, ArrayList<MemSample>>(); |
|
743 Iterator<ProfiledLibraryEvent> iterator = drawDataByLibraryEvent.values().iterator(); |
|
744 while(iterator.hasNext()){ |
|
745 ProfiledLibraryEvent ple = iterator.next(); |
|
746 Iterator<MemSample> iteratorMem = ple.getMemSamples().values().iterator(); |
|
747 while(iteratorMem.hasNext()){ |
|
748 MemSample memSample = iteratorMem.next(); |
|
749 ArrayList<MemSample> memSamples = drawLibraryEventDataByTime.get(memSample.sampleSynchTime); |
|
750 if(memSamples == null){ |
|
751 memSamples = new ArrayList<MemSample>(); |
|
752 } |
|
753 memSamples.add(memSample); |
|
754 drawLibraryEventDataByTime.put(memSample.sampleSynchTime, memSamples); |
|
755 } |
|
756 } |
|
757 } |
|
758 |
|
759 ArrayList<MemSample> retMemSamples = new ArrayList<MemSample>(); |
|
760 ArrayList<MemSample> bestChoice = null; |
|
761 scale = (long)scale * 5; |
|
762 |
|
763 if(scale == 0){ |
|
764 bestChoice = drawLibraryEventDataByTime.get(time); |
|
765 } else { |
|
766 SortedMap<Long, ArrayList<MemSample>> sortedMap = drawLibraryEventDataByTime |
|
767 .subMap(time - scale, time + scale); |
|
768 long min = Long.MAX_VALUE; |
|
769 long closest = time; |
|
770 for (Long key : sortedMap.keySet()) { |
|
771 final long diff = Math.abs(key - time); |
|
772 if (diff < min) { |
|
773 Iterator<MemSample> iterator = sortedMap.get(key).iterator(); |
|
774 while(iterator.hasNext()){ |
|
775 MemSample memSample = iterator.next(); |
|
776 if(memSample.thread.isEnabled(graphIndex)){ |
|
777 min = diff; |
|
778 closest = key; |
|
779 } |
|
780 } |
|
781 } |
|
782 } |
|
783 bestChoice = sortedMap.get(closest); |
|
784 } |
|
785 if(bestChoice != null){ |
|
786 Iterator<MemSample> iterator = bestChoice.iterator(); |
|
787 while(iterator.hasNext()){ |
|
788 MemSample memSample = iterator.next(); |
|
789 if(memSample.thread.isEnabled(graphIndex)){ |
|
790 retMemSamples.add(memSample); |
|
791 } |
|
792 } |
|
793 } |
|
794 return retMemSamples; |
|
795 } |
|
796 |
|
797 public String getLibraryNameString(String fullName){ |
|
798 int startIndex = fullName.indexOf("::") + 2; //$NON-NLS-1$ |
|
799 int lastIndex = fullName.indexOf(" ["); //$NON-NLS-1$ |
|
800 if(startIndex != -1 && lastIndex != -1){ |
|
801 return fullName.substring(startIndex, lastIndex); |
|
802 } |
|
803 return null; |
|
804 } |
|
805 |
|
806 public String getProcessFromLibraryNameString(String fullName){ |
|
807 int lastIndex = fullName.indexOf("::"); //$NON-NLS-1$ |
|
808 if(lastIndex != -1){ |
|
809 return fullName.substring(0, lastIndex); |
|
810 } |
|
811 return null; |
|
812 } |
655 |
813 |
656 } |
814 } |