1 /**********************************************************************
2 * Copyright (c) 2014, 2016 Ericsson, École Polytechnique de Montréal
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Matthew Khouzam - Initial API and implementation
11 * Geneviève Bastien - Memory is per thread and only total is kept
12 **********************************************************************/
14 package org
.eclipse
.tracecompass
.internal
.lttng2
.ust
.core
.analysis
.memory
;
16 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
18 import java
.util
.HashMap
;
21 import org
.eclipse
.jdt
.annotation
.NonNull
;
22 import org
.eclipse
.tracecompass
.lttng2
.ust
.core
.trace
.LttngUstTrace
;
23 import org
.eclipse
.tracecompass
.lttng2
.ust
.core
.trace
.layout
.ILttngUstEventLayout
;
24 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystemBuilder
;
25 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventField
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.AbstractTmfStateProvider
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.ITmfStateProvider
;
34 import com
.google
.common
.collect
.ImmutableMap
;
37 * State provider to track the memory of the threads using the UST libc wrapper
44 * | |- UST_MEMORY_MEMORY_ATTRIBUTE -> Memory Usage
45 * | |- UST_MEMORY_PROCNAME_ATTRIBUTE -> Process name
48 * @author Matthew Khouzam
49 * @author Geneviève Bastien
51 public class UstMemoryStateProvider
extends AbstractTmfStateProvider
{
53 /* Version of this state provider */
54 private static final int VERSION
= 1;
56 private static final Long MINUS_ONE
= Long
.valueOf(-1);
57 private static final Long ZERO
= Long
.valueOf(0);
58 private static final String EMPTY_STRING
= ""; //$NON-NLS-1$
60 private static final int MALLOC_INDEX
= 1;
61 private static final int FREE_INDEX
= 2;
62 private static final int CALLOC_INDEX
= 3;
63 private static final int REALLOC_INDEX
= 4;
64 private static final int MEMALIGN_INDEX
= 5;
65 private static final int POSIX_MEMALIGN_INDEX
= 6;
67 /** Map of a pointer to a memory zone to the size of the memory */
68 private final Map
<Long
, Long
> fMemory
= new HashMap
<>();
70 private final @NonNull ILttngUstEventLayout fLayout
;
71 private final @NonNull Map
<String
, Integer
> fEventNames
;
79 public UstMemoryStateProvider(@NonNull LttngUstTrace trace
) {
80 super(trace
, "Ust:Memory"); //$NON-NLS-1$
81 fLayout
= trace
.getEventLayout();
82 fEventNames
= buildEventNames(fLayout
);
85 private static @NonNull Map
<String
, Integer
> buildEventNames(ILttngUstEventLayout layout
) {
86 ImmutableMap
.Builder
<String
, Integer
> builder
= ImmutableMap
.builder();
87 builder
.put(layout
.eventLibcMalloc(), MALLOC_INDEX
);
88 builder
.put(layout
.eventLibcFree(), FREE_INDEX
);
89 builder
.put(layout
.eventLibcCalloc(), CALLOC_INDEX
);
90 builder
.put(layout
.eventLibcRealloc(), REALLOC_INDEX
);
91 builder
.put(layout
.eventLibcMemalign(), MEMALIGN_INDEX
);
92 builder
.put(layout
.eventLibcPosixMemalign(), POSIX_MEMALIGN_INDEX
);
93 return builder
.build();
97 protected void eventHandle(ITmfEvent event
) {
98 String name
= event
.getName();
99 Integer index
= fEventNames
.get(name
);
100 int intIndex
= (index
== null ?
-1 : index
.intValue());
104 Long ptr
= (Long
) event
.getContent().getField(fLayout
.fieldPtr()).getValue();
105 if (ZERO
.equals(ptr
)) {
108 Long size
= (Long
) event
.getContent().getField(fLayout
.fieldSize()).getValue();
109 setMem(event
, ptr
, size
);
113 Long ptr
= (Long
) event
.getContent().getField(fLayout
.fieldPtr()).getValue();
114 if (ZERO
.equals(ptr
)) {
117 setMem(event
, ptr
, ZERO
);
121 Long ptr
= (Long
) event
.getContent().getField(fLayout
.fieldPtr()).getValue();
122 if (ZERO
.equals(ptr
)) {
125 Long nmemb
= (Long
) event
.getContent().getField(fLayout
.fieldNmemb()).getValue();
126 Long size
= (Long
) event
.getContent().getField(fLayout
.fieldSize()).getValue();
127 setMem(event
, ptr
, size
* nmemb
);
130 case REALLOC_INDEX
: {
131 Long ptr
= (Long
) event
.getContent().getField(fLayout
.fieldPtr()).getValue();
132 if (ZERO
.equals(ptr
)) {
135 Long newPtr
= (Long
) event
.getContent().getField(fLayout
.fieldInPtr()).getValue();
136 Long size
= (Long
) event
.getContent().getField(fLayout
.fieldSize()).getValue();
137 setMem(event
, ptr
, ZERO
);
138 setMem(event
, newPtr
, size
);
141 case MEMALIGN_INDEX
: {
142 Long ptr
= (Long
) event
.getContent().getField(fLayout
.fieldPtr()).getValue();
143 if (ZERO
.equals(ptr
)) {
146 Long size
= (Long
) event
.getContent().getField(fLayout
.fieldSize()).getValue();
147 setMem(event
, ptr
, size
);
150 case POSIX_MEMALIGN_INDEX
: {
151 Long ptr
= (Long
) event
.getContent().getField(fLayout
.fieldOutPtr()).getValue();
152 if (ZERO
.equals(ptr
)) {
155 Long size
= (Long
) event
.getContent().getField(fLayout
.fieldSize()).getValue();
156 setMem(event
, ptr
, size
);
160 /* Ignore other event types */
167 public ITmfStateProvider
getNewInstance() {
168 return new UstMemoryStateProvider(getTrace());
172 public LttngUstTrace
getTrace() {
173 return (LttngUstTrace
) super.getTrace();
177 public int getVersion() {
181 private Long
getVtid(ITmfEvent event
) {
182 ITmfEventField field
= event
.getContent().getField(fLayout
.contextVtid());
186 return (Long
) field
.getValue();
189 private String
getProcname(ITmfEvent event
) {
190 ITmfEventField field
= event
.getContent().getField(fLayout
.contextProcname());
194 return (String
) field
.getValue();
197 private void setMem(ITmfEvent event
, Long ptr
, Long size
) {
198 ITmfStateSystemBuilder ss
= checkNotNull(getStateSystemBuilder());
199 long ts
= event
.getTimestamp().toNanos();
200 Long tid
= getVtid(event
);
202 Long memoryDiff
= size
;
203 /* Size is 0, it means it was deleted */
204 if (ZERO
.equals(size
)) {
205 Long memSize
= fMemory
.remove(ptr
);
206 if (memSize
== null) {
209 memoryDiff
= -memSize
;
211 fMemory
.put(ptr
, size
);
214 int tidQuark
= ss
.getQuarkAbsoluteAndAdd(tid
.toString());
215 int tidMemQuark
= ss
.getQuarkRelativeAndAdd(tidQuark
, UstMemoryStrings
.UST_MEMORY_MEMORY_ATTRIBUTE
);
217 ITmfStateValue prevMem
= ss
.queryOngoingState(tidMemQuark
);
218 /* First time we set this value */
219 if (prevMem
.isNull()) {
220 int procNameQuark
= ss
.getQuarkRelativeAndAdd(tidQuark
, UstMemoryStrings
.UST_MEMORY_PROCNAME_ATTRIBUTE
);
221 String procName
= getProcname(event
);
223 * No tid/procname for the event for the event, added to a
226 if (tid
.equals(MINUS_ONE
)) {
227 procName
= UstMemoryStrings
.OTHERS
;
229 ss
.modifyAttribute(ts
, TmfStateValue
.newValueString(procName
), procNameQuark
);
230 prevMem
= TmfStateValue
.newValueLong(0);
233 long prevMemValue
= prevMem
.unboxLong();
234 prevMemValue
+= memoryDiff
.longValue();
235 ss
.modifyAttribute(ts
, TmfStateValue
.newValueLong(prevMemValue
), tidMemQuark
);
236 } catch (TimeRangeException
| StateValueTypeException e
) {
237 throw new IllegalStateException(e
);