1 /*******************************************************************************
2 * Copyright (c) 2015 EfficiOS Inc., Ericsson
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.latency
;
12 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
14 import java
.io
.IOException
;
15 import java
.io
.ObjectInputStream
;
16 import java
.io
.ObjectOutputStream
;
17 import java
.nio
.file
.Files
;
18 import java
.nio
.file
.Path
;
19 import java
.nio
.file
.Paths
;
20 import java
.util
.HashMap
;
21 import java
.util
.HashSet
;
25 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
26 import org
.eclipse
.jdt
.annotation
.Nullable
;
27 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernelanalysis
.KernelTidAspect
;
28 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.trace
.IKernelAnalysisEventLayout
;
29 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.trace
.IKernelTrace
;
30 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
31 import org
.eclipse
.tracecompass
.segmentstore
.core
.ISegment
;
32 import org
.eclipse
.tracecompass
.segmentstore
.core
.ISegmentStore
;
33 import org
.eclipse
.tracecompass
.segmentstore
.core
.treemap
.TreeMapStore
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.analysis
.TmfAbstractAnalysisModule
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
36 import org
.eclipse
.tracecompass
.tmf
.core
.exceptions
.TmfAnalysisException
;
37 import org
.eclipse
.tracecompass
.tmf
.core
.request
.ITmfEventRequest
;
38 import org
.eclipse
.tracecompass
.tmf
.core
.request
.TmfEventRequest
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
41 import com
.google
.common
.base
.Function
;
42 import com
.google
.common
.collect
.FluentIterable
;
45 * @author Alexandre Montplaisir
48 public class LatencyAnalysis
extends TmfAbstractAnalysisModule
{
51 * The ID of this analysis
53 public static final String ID
= "org.eclipse.tracecompass.analysis.os.linux.latency"; //$NON-NLS-1$
55 private static final String DATA_FILENAME
= "latency-analysis.dat"; //$NON-NLS-1$
57 private @Nullable ISegmentStore
<ISegment
> fSystemCalls
;
59 private final Set
<LatencyAnalysisListener
> fListeners
= new HashSet
<>();
62 public String
getId() {
67 * Listener for the viewers
70 * listener for each type of viewer
72 public void addListener(LatencyAnalysisListener listener
) {
73 fListeners
.add(listener
);
77 protected boolean executeAnalysis(IProgressMonitor monitor
) throws TmfAnalysisException
{
78 IKernelTrace trace
= checkNotNull((IKernelTrace
) getTrace());
79 IKernelAnalysisEventLayout layout
= trace
.getKernelEventLayout();
81 /* See if the data file already exists on disk */
82 String dir
= TmfTraceManager
.getSupplementaryFileDir(trace
);
83 final Path file
= Paths
.get(dir
, DATA_FILENAME
);
85 if (Files
.exists(file
)) {
86 /* Attempt to read the existing file */
87 try (ObjectInputStream ois
= new ObjectInputStream(Files
.newInputStream(file
))) {
88 @SuppressWarnings("unchecked")
89 ISegmentStore
<ISegment
> syscalls
= (ISegmentStore
<ISegment
>) ois
.readObject();
90 fSystemCalls
= syscalls
;
92 } catch (IOException
| ClassNotFoundException
| ClassCastException e
) {
94 * We did not manage to read the file successfully, we will just
95 * fall-through to rebuild a new one.
99 } catch (IOException e1
) {
104 ISegmentStore
<ISegment
> syscalls
= new TreeMapStore
<>();
105 ITmfEventRequest req
= new LatencyAnalysisRequest(layout
, syscalls
);
106 trace
.sendRequest(req
);
108 req
.waitForCompletion();
109 } catch (InterruptedException e
) {
111 /* The request will fill 'syscalls' */
112 fSystemCalls
= syscalls
;
114 /* Serialize the collections to disk for future usage */
115 try (ObjectOutputStream oos
= new ObjectOutputStream(Files
.newOutputStream(file
))) {
116 oos
.writeObject(syscalls
);
117 } catch (IOException e
) {
118 /* Didn't work, oh well. We will just re-read the trace next time */
121 for (LatencyAnalysisListener listener
: fListeners
) {
122 listener
.onComplete(this, syscalls
);
129 protected void canceling() {
134 * @return Results from the analysis in a ISegmentStore
136 public @Nullable ISegmentStore
<ISegment
> getResults() {
140 private static class LatencyAnalysisRequest
extends TmfEventRequest
{
142 private final IKernelAnalysisEventLayout fLayout
;
143 private final ISegmentStore
<ISegment
> fFullSyscalls
;
144 private final Map
<Integer
, SystemCall
.InitialInfo
> fOngoingSystemCalls
= new HashMap
<>();
146 public LatencyAnalysisRequest(IKernelAnalysisEventLayout layout
, ISegmentStore
<ISegment
> syscalls
) {
147 super(ITmfEvent
.class, 0, ITmfEventRequest
.ALL_DATA
, ExecutionType
.BACKGROUND
);
150 * We do NOT make a copy here! We want to modify the list that was
151 * passed in parameter.
153 fFullSyscalls
= syscalls
;
157 public void handleData(final ITmfEvent event
) {
158 super.handleData(event
);
159 final String eventName
= event
.getType().getName();
161 if (eventName
.startsWith(fLayout
.eventSyscallEntryPrefix()) ||
162 eventName
.startsWith(fLayout
.eventCompatSyscallEntryPrefix())) {
163 /* This is a system call entry event */
165 Integer tid
= KernelTidAspect
.INSTANCE
.resolve(event
);
167 // no information on this event/trace ?
171 /* Record the event's data into the intial system call info */
172 // String syscallName = fLayout.getSyscallNameFromEvent(event);
173 long startTime
= event
.getTimestamp().getValue();
174 String syscallName
= eventName
.substring(fLayout
.eventSyscallEntryPrefix().length());
175 FluentIterable
<String
> argNames
= FluentIterable
.from(event
.getContent().getFieldNames());
176 Map
<String
, String
> args
= argNames
.toMap(new Function
<String
, String
>() {
178 public String
apply(@Nullable String input
) {
179 return checkNotNull(event
.getContent().getField(input
).getValue().toString());
182 SystemCall
.InitialInfo newSysCall
= new SystemCall
.InitialInfo(startTime
, NonNullUtils
.checkNotNull(syscallName
), NonNullUtils
.checkNotNull(args
));
183 fOngoingSystemCalls
.put(tid
, newSysCall
);
185 } else if (eventName
.startsWith(fLayout
.eventSyscallExitPrefix())) {
186 /* This is a system call exit event */
188 Integer tid
= KernelTidAspect
.INSTANCE
.resolve(event
);
193 SystemCall
.InitialInfo info
= fOngoingSystemCalls
.remove(tid
);
196 * We have not seen the entry event corresponding to this
197 * exit (lost event, or before start of trace).
202 long endTime
= event
.getTimestamp().getValue();
203 int ret
= ((Long
) event
.getContent().getField("ret").getValue()).intValue(); //$NON-NLS-1$
204 ISegment syscall
= new SystemCall(info
, endTime
, ret
);
205 fFullSyscalls
.add(syscall
);
210 public void handleCompleted() {
211 fOngoingSystemCalls
.clear();