1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 Ericsson
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 * Alexandre Montplaisir - Initial API and implementation
11 * Patrick Tasse - Fix TimeRangeException
12 ******************************************************************************/
14 package org
.eclipse
.tracecompass
.tmf
.core
.statistics
;
16 import java
.util
.HashMap
;
17 import java
.util
.LinkedList
;
18 import java
.util
.List
;
21 import org
.eclipse
.jdt
.annotation
.NonNull
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
23 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
24 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
25 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
28 * Implementation of ITmfStatistics which uses a state history for storing its
29 * information. In reality, it uses two state histories, one for "event totals"
30 * information (which should ideally use a fast backend), and another one for
31 * the rest (per event type, per CPU, etc.).
33 * Compared to the event-request-based statistics calculations, it adds the
34 * building the history first, but gives much faster response times once built :
35 * Queries are O(log n) wrt the size of the trace, and O(1) wrt to the size of
36 * the time interval selected.
38 * @author Alexandre Montplaisir
40 public class TmfStateStatistics
implements ITmfStatistics
{
42 // ------------------------------------------------------------------------
44 // ------------------------------------------------------------------------
46 /** The event totals state system */
47 private final ITmfStateSystem totalsStats
;
49 /** The state system for event types */
50 private final ITmfStateSystem typesStats
;
52 // ------------------------------------------------------------------------
54 // ------------------------------------------------------------------------
60 * The state system containing the "totals" information
62 * The state system containing the "event types" information
64 public TmfStateStatistics(@NonNull ITmfStateSystem totals
, @NonNull ITmfStateSystem eventTypes
) {
65 this.totalsStats
= totals
;
66 this.typesStats
= eventTypes
;
70 * Return the state system containing the "totals" values
72 * @return The "totals" state system
74 public ITmfStateSystem
getTotalsSS() {
79 * Return the state system containing the "event types" values
81 * @return The "event types" state system
83 public ITmfStateSystem
getEventTypesSS() {
87 // ------------------------------------------------------------------------
89 // ------------------------------------------------------------------------
92 public void dispose() {
93 totalsStats
.dispose();
98 public List
<Long
> histogramQuery(final long start
, final long end
, final int nb
) {
99 final List
<Long
> list
= new LinkedList
<>();
100 final long increment
= (end
- start
) / nb
;
102 if (totalsStats
.isCancelled()) {
107 * We will do one state system query per "border", and save the
108 * differences between each border.
110 long prevTotal
= (start
== totalsStats
.getStartTime()) ?
0 : getEventCountAt(start
);
111 long curTime
= start
+ increment
;
113 long curTotal
, count
;
114 for (int i
= 0; i
< nb
- 1; i
++) {
115 curTotal
= getEventCountAt(curTime
);
116 count
= curTotal
- prevTotal
;
119 curTime
+= increment
;
120 prevTotal
= curTotal
;
124 * For the last bucket, we'll stretch its end time to the end time of
125 * the requested range, in case it got truncated down.
127 curTotal
= getEventCountAt(end
);
128 count
= curTotal
- prevTotal
;
135 public long getEventsTotal() {
136 long endTime
= totalsStats
.getCurrentEndTime();
140 final int quark
= totalsStats
.getQuarkAbsolute(Attributes
.TOTAL
);
141 count
= totalsStats
.querySingleState(endTime
, quark
).getStateValue().unboxInt();
143 } catch (StateSystemDisposedException e
) {
144 /* Assume there is no events for that range */
146 } catch (AttributeNotFoundException e
) {
154 public Map
<String
, Long
> getEventTypesTotal() {
155 final Map
<String
, Long
> map
= new HashMap
<>();
156 long endTime
= typesStats
.getCurrentEndTime();
159 /* Get the list of quarks, one for each even type in the database */
160 int quark
= typesStats
.getQuarkAbsolute(Attributes
.EVENT_TYPES
);
161 List
<Integer
> quarks
= typesStats
.getSubAttributes(quark
, false);
163 /* Since we want the total we can look only at the end */
164 List
<ITmfStateInterval
> endState
= typesStats
.queryFullState(endTime
);
168 for (int typeQuark
: quarks
) {
169 curEventName
= typesStats
.getAttributeName(typeQuark
);
170 eventCount
= endState
.get(typeQuark
).getStateValue().unboxInt();
171 map
.put(curEventName
, eventCount
);
174 } catch (StateSystemDisposedException e
) {
175 /* Assume there is no events, nothing will be put in the map. */
176 } catch (AttributeNotFoundException e
) {
183 public long getEventsInRange(long start
, long end
) {
185 if (start
== totalsStats
.getStartTime()) {
189 * We want the events happening at "start" to be included, so we'll
190 * need to query one unit before that point.
192 startCount
= getEventCountAt(start
- 1);
194 long endCount
= getEventCountAt(end
);
196 return endCount
- startCount
;
200 public Map
<String
, Long
> getEventTypesInRange(long start
, long end
) {
201 final Map
<String
, Long
> map
= new HashMap
<>();
202 List
<Integer
> quarks
;
204 /* Make sure the start/end times are within the state history, so we
205 * don't get TimeRange exceptions.
207 long startTime
= checkStartTime(start
, typesStats
);
208 long endTime
= checkEndTime(end
, typesStats
);
209 if (endTime
< startTime
) {
210 /* The start/end times do not intersect this state system range.
211 * Return the empty map. */
216 /* Get the list of quarks, one for each even type in the database */
217 int quark
= typesStats
.getQuarkAbsolute(Attributes
.EVENT_TYPES
);
218 quarks
= typesStats
.getSubAttributes(quark
, false);
219 } catch (AttributeNotFoundException e
) {
221 * The state system does not (yet?) have the needed attributes, it
222 * probably means there are no events counted yet. Return the empty
229 List
<ITmfStateInterval
> endState
= typesStats
.queryFullState(endTime
);
231 if (startTime
== typesStats
.getStartTime()) {
232 /* Only use the values picked up at the end time */
233 for (int typeQuark
: quarks
) {
234 String curEventName
= typesStats
.getAttributeName(typeQuark
);
235 long eventCount
= endState
.get(typeQuark
).getStateValue().unboxInt();
236 if (eventCount
== -1) {
239 map
.put(curEventName
, eventCount
);
243 * Query the start time at -1, so the beginning of the interval
246 List
<ITmfStateInterval
> startState
= typesStats
.queryFullState(startTime
- 1);
247 for (int typeQuark
: quarks
) {
248 String curEventName
= typesStats
.getAttributeName(typeQuark
);
249 long countAtStart
= startState
.get(typeQuark
).getStateValue().unboxInt();
250 long countAtEnd
= endState
.get(typeQuark
).getStateValue().unboxInt();
252 if (countAtStart
== -1) {
255 if (countAtEnd
== -1) {
258 long eventCount
= countAtEnd
- countAtStart
;
259 map
.put(curEventName
, eventCount
);
263 } catch (StateSystemDisposedException e
) {
264 /* Assume there is no (more) events, nothing will be put in the map. */
269 // ------------------------------------------------------------------------
271 // ------------------------------------------------------------------------
273 private long getEventCountAt(long timestamp
) {
274 /* Make sure the target time is within the range of the history */
275 long ts
= checkStartTime(timestamp
, totalsStats
);
276 ts
= checkEndTime(ts
, totalsStats
);
279 final int quark
= totalsStats
.getQuarkAbsolute(Attributes
.TOTAL
);
280 long count
= totalsStats
.querySingleState(ts
, quark
).getStateValue().unboxInt();
283 } catch (StateSystemDisposedException e
) {
284 /* Assume there is no (more) events, nothing will be put in the map. */
285 } catch (AttributeNotFoundException e
) {
292 private static long checkStartTime(long initialStart
, ITmfStateSystem ss
) {
293 long start
= initialStart
;
294 if (start
< ss
.getStartTime()) {
295 return ss
.getStartTime();
300 private static long checkEndTime(long initialEnd
, ITmfStateSystem ss
) {
301 long end
= initialEnd
;
302 if (end
> ss
.getCurrentEndTime()) {
303 return ss
.getCurrentEndTime();
309 * The attribute names that are used in the state provider
311 public static class Attributes
{
313 /** Total nb of events */
314 public static final String TOTAL
= "total"; //$NON-NLS-1$
317 public static final String EVENT_TYPES
= "event_types"; //$NON-NLS-1$<