From: Matthew Khouzam Date: Tue, 17 May 2016 15:01:03 +0000 (-0400) Subject: linux.core: internalize System Call Analysis X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=660d4ed9bd22ac357b49953bad1f11f5893747de;p=deliverable%2Ftracecompass.git linux.core: internalize System Call Analysis This analysis is an implementation of the segment store, it should be internal Change-Id: Ifc246608b65c5f09ae11ac2386ee31d462bce825 Signed-off-by: Matthew Khouzam Reviewed-on: https://git.eclipse.org/r/72938 Reviewed-by: Genevieve Bastien Reviewed-by: Hudson CI Tested-by: Genevieve Bastien Reviewed-by: Marc-Andre Laperle Tested-by: Marc-Andre Laperle --- diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF index 981f8f62fc..df25f432dd 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF @@ -25,7 +25,6 @@ Export-Package: org.eclipse.tracecompass.analysis.os.linux.core.contextswitch, org.eclipse.tracecompass.analysis.os.linux.core.inputoutput;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui,org.eclipse.tracecompass.analysis.os.linux.core.tests", org.eclipse.tracecompass.analysis.os.linux.core.kernel, org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage, - org.eclipse.tracecompass.analysis.os.linux.core.latency, org.eclipse.tracecompass.analysis.os.linux.core.model, org.eclipse.tracecompass.analysis.os.linux.core.signals, org.eclipse.tracecompass.analysis.os.linux.core.tid, @@ -33,9 +32,7 @@ Export-Package: org.eclipse.tracecompass.analysis.os.linux.core.contextswitch, org.eclipse.tracecompass.internal.analysis.os.linux.core;x-internal:=true, org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui,org.eclipse.tracecompass.analysis.os.linux.core.tests", org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers;x-internal:=true, - org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel; - x-friends:="org.eclipse.tracecompass.analysis.os.linux.core.tests, - org.eclipse.tracecompass.analysis.os.linux.ui, - org.eclipse.tracecompass.lttng2.kernel.core.tests", + org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel;x-friends:="org.eclipse.tracecompass.analysis.os.linux.core.tests,org.eclipse.tracecompass.analysis.os.linux.ui,org.eclipse.tracecompass.lttng2.kernel.core.tests", org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers;x-friends:="org.eclipse.tracecompass.analysis.os.linux.core.tests", + org.eclipse.tracecompass.internal.analysis.os.linux.core.latency;x-friends:="org.eclipse.tracecompass.analysis.os.linux.core.tests,org.eclipse.tracecompass.analysis.os.linux.ui", org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.statistics;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui,org.eclipse.tracecompass.analysis.os.linux.core.tests" diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.xml b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.xml index 300647bcae..d6c7816b56 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.xml +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.xml @@ -24,7 +24,7 @@ diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/Messages.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/Messages.java deleted file mode 100644 index dabf9ea34b..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/Messages.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Ericsson - * - * All rights reserved. This program and the accompanying materials are made - * available under the terms of the Eclipse Public License v1.0 which - * accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ - -package org.eclipse.tracecompass.analysis.os.linux.core.latency; - -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.osgi.util.NLS; - -/** - * Messages for Syscall latency analysis. - * @since 2.0 - */ -public class Messages extends NLS { - - private static final String BUNDLE_NAME = "org.eclipse.tracecompass.analysis.os.linux.core.latency.messages"; //$NON-NLS-1$ - - /** System Call latency analysis aspect name */ - public static @Nullable String SegmentAspectName_SystemCall; - - /** System Call latency analysis aspect help text */ - public static @Nullable String SegmentAspectHelpText_SystemCall; - - static { - NLS.initializeMessages(BUNDLE_NAME, Messages.class); - } - - private Messages() { - } - - /** - * Helper method to expose externalized strings as non-null objects. - */ - static String getMessage(@Nullable String msg) { - if (msg == null) { - return ""; //$NON-NLS-1$ - } - return msg; - } -} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/SystemCall.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/SystemCall.java deleted file mode 100644 index 0ccaadc8d0..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/SystemCall.java +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ - -package org.eclipse.tracecompass.analysis.os.linux.core.latency; - -import java.io.Serializable; -import java.util.Map; - -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.tracecompass.segmentstore.core.ISegment; - -import com.google.common.collect.ImmutableMap; - -/** - * A linux kernel system call, represented as an {@link ISegment}. - * - * @author Alexandre Montplaisir - * @since 2.0 - */ -public class SystemCall implements ISegment { - - private static final long serialVersionUID = 1554494342105208730L; - - /** - * The subset of information that is available from the syscall entry event. - */ - public static class InitialInfo implements Serializable { - - private static final long serialVersionUID = -5009710718804983721L; - - private final long fStartTime; - private final String fName; - private final Map fArgs; - - /** - * @param startTime - * Start time of the system call - * @param name - * Name of the system call - * @param arguments - * Arguments of the system call - */ - public InitialInfo( - long startTime, - String name, - Map arguments) { - fStartTime = startTime; - fName = name; - fArgs = ImmutableMap.copyOf(arguments); - } - } - - private final InitialInfo fInfo; - private final long fEndTime; - private final int fRet; - - /** - * @param info - * Initial information of the system call - * @param endTime - * End time of the system call - * @param ret - * Return value of the system call - */ - public SystemCall( - InitialInfo info, - long endTime, - int ret) { - fInfo = info; - fEndTime = endTime; - fRet = ret; - } - - @Override - public long getStart() { - return fInfo.fStartTime; - } - - @Override - public long getEnd() { - return fEndTime; - } - - /** - * Get the name of the system call - * - * @return Name - */ - public String getName() { - return fInfo.fName; - } - - /** - * Get the arguments of the system call - * - * @return Map of the arguments - */ - public Map getArguments() { - return fInfo.fArgs; - } - - /** - * Get the return value of the system call - * - * @return Return value - */ - public int getReturnValue() { - return fRet; - } - - @Override - public int compareTo(@NonNull ISegment o) { - int ret = ISegment.super.compareTo(o); - if (ret != 0) { - return ret; - } - return toString().compareTo(o.toString()); - } - - @Override - public String toString() { - return "Start Time = " + getStart() + //$NON-NLS-1$ - "; End Time = " + getEnd() + //$NON-NLS-1$ - "; Duration = " + getLength() + //$NON-NLS-1$ - "; Name = " + getName() + //$NON-NLS-1$ - "; Args = " + getArguments().toString() + //$NON-NLS-1$ - "; Return = " + getReturnValue(); //$NON-NLS-1$ - } -} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/SystemCallLatencyAnalysis.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/SystemCallLatencyAnalysis.java deleted file mode 100644 index e324337cf8..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/SystemCallLatencyAnalysis.java +++ /dev/null @@ -1,213 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015, 2016 EfficiOS Inc., Ericsson - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ - -package org.eclipse.tracecompass.analysis.os.linux.core.latency; - -import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelTidAspect; -import org.eclipse.tracecompass.analysis.os.linux.core.tid.TidAnalysisModule; -import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout; -import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace; -import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisEventBasedModule; -import org.eclipse.tracecompass.segmentstore.core.ISegment; -import org.eclipse.tracecompass.segmentstore.core.ISegmentStore; -import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; -import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; -import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect; -import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -/** - * @author Alexandre Montplaisir - * @since 2.0 - */ -public class SystemCallLatencyAnalysis extends AbstractSegmentStoreAnalysisEventBasedModule { - - /** - * The ID of this analysis - */ - public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.latency.syscall"; //$NON-NLS-1$ - - private static final String DATA_FILENAME = "latency-analysis.dat"; //$NON-NLS-1$ - - private static final Collection BASE_ASPECTS = - ImmutableList.of(SyscallNameAspect.INSTANCE); - - @Override - public String getId() { - return ID; - } - - @Override - protected Iterable getDependentAnalyses() { - ITmfTrace trace = getTrace(); - if (trace == null) { - throw new IllegalStateException(); - } - IAnalysisModule module = trace.getAnalysisModule(TidAnalysisModule.ID); - if (module == null) { - return Collections.EMPTY_SET; - } - return ImmutableSet.of(module); - } - - @Override - public Iterable getSegmentAspects() { - return BASE_ASPECTS; - } - - @Override - public @NonNull String getDataFileName() { - return DATA_FILENAME; - } - - @Override - public AbstractSegmentStoreAnalysisRequest createAnalysisRequest(ISegmentStore syscalls) { - return new SyscallLatencyAnalysisRequest(syscalls); - } - - @Override - protected Object[] readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { - return checkNotNull((Object[]) ois.readObject()); - } - - private class SyscallLatencyAnalysisRequest extends AbstractSegmentStoreAnalysisRequest { - - private final Map fOngoingSystemCalls = new HashMap<>(); - private @Nullable IKernelAnalysisEventLayout fLayout; - private final IProgressMonitor fMonitor = new NullProgressMonitor(); - - public SyscallLatencyAnalysisRequest(ISegmentStore syscalls) { - super(syscalls); - } - - @Override - public void handleData(final ITmfEvent event) { - super.handleData(event); - IKernelAnalysisEventLayout layout = fLayout; - if (layout == null) { - IKernelTrace trace = (IKernelTrace) event.getTrace(); - layout = trace.getKernelEventLayout(); - fLayout = layout; - } - final String eventName = event.getType().getName(); - - if (eventName.startsWith(layout.eventSyscallEntryPrefix()) || - eventName.startsWith(layout.eventCompatSyscallEntryPrefix())) { - /* This is a system call entry event */ - - Integer tid; - try { - tid = KernelTidAspect.INSTANCE.resolve(event, true, fMonitor); - } catch (InterruptedException e) { - return; - } - if (tid == null) { - // no information on this event/trace ? - return; - } - - /* Record the event's data into the intial system call info */ - // String syscallName = fLayout.getSyscallNameFromEvent(event); - long startTime = event.getTimestamp().getValue(); - String syscallName = eventName.substring(layout.eventSyscallEntryPrefix().length()); - - Map args = event.getContent().getFieldNames().stream() - .collect(Collectors.toMap(Function.identity(), - input -> checkNotNull(event.getContent().getField(input).toString()))); - - SystemCall.InitialInfo newSysCall = new SystemCall.InitialInfo(startTime, checkNotNull(syscallName), checkNotNull(args)); - fOngoingSystemCalls.put(tid, newSysCall); - - } else if (eventName.startsWith(layout.eventSyscallExitPrefix())) { - /* This is a system call exit event */ - - Integer tid; - try { - tid = KernelTidAspect.INSTANCE.resolve(event, true, fMonitor); - } catch (InterruptedException e) { - return; - } - if (tid == null) { - return; - } - - SystemCall.InitialInfo info = fOngoingSystemCalls.remove(tid); - if (info == null) { - /* - * We have not seen the entry event corresponding to this - * exit (lost event, or before start of trace). - */ - return; - } - - long endTime = event.getTimestamp().getValue(); - int ret = ((Long) event.getContent().getField("ret").getValue()).intValue(); //$NON-NLS-1$ - ISegment syscall = new SystemCall(info, endTime, ret); - getSegmentStore().add(syscall); - } - } - - @Override - public void handleCompleted() { - fOngoingSystemCalls.clear(); - super.handleCompleted(); - } - - @Override - public void handleCancel() { - fMonitor.setCanceled(true); - super.handleCancel(); - } - } - - private static class SyscallNameAspect implements ISegmentAspect { - public static final ISegmentAspect INSTANCE = new SyscallNameAspect(); - - private SyscallNameAspect() { } - - @Override - public String getHelpText() { - return checkNotNull(Messages.SegmentAspectHelpText_SystemCall); - } - @Override - public String getName() { - return checkNotNull(Messages.SegmentAspectName_SystemCall); - } - @Override - public @Nullable Comparator getComparator() { - return null; - } - @Override - public @Nullable String resolve(ISegment segment) { - if (segment instanceof SystemCall) { - return ((SystemCall) segment).getName(); - } - return EMPTY_STRING; - } - } - -} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/messages.properties b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/messages.properties deleted file mode 100644 index f1692c17c1..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/messages.properties +++ /dev/null @@ -1,12 +0,0 @@ -############################################################################### -# Copyright (c) 2015 Ericsson -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -############################################################################### - -SegmentAspectName_SystemCall=System Call - -SegmentAspectHelpText_SystemCall=The name of the system call. diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/package-info.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/package-info.java deleted file mode 100644 index 2ad2c43b26..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/latency/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Ericsson - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ - -@org.eclipse.jdt.annotation.NonNullByDefault -package org.eclipse.tracecompass.analysis.os.linux.core.latency; diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/Messages.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/Messages.java new file mode 100644 index 0000000000..99a7ea7f74 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/Messages.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2015 Ericsson + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.os.linux.core.latency; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.osgi.util.NLS; + +/** + * Messages for Syscall latency analysis. + * @since 2.0 + */ +public class Messages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.messages"; //$NON-NLS-1$ + + /** System Call latency analysis aspect name */ + public static @Nullable String SegmentAspectName_SystemCall; + + /** System Call latency analysis aspect help text */ + public static @Nullable String SegmentAspectHelpText_SystemCall; + + static { + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } + + /** + * Helper method to expose externalized strings as non-null objects. + */ + static String getMessage(@Nullable String msg) { + if (msg == null) { + return ""; //$NON-NLS-1$ + } + return msg; + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/SystemCall.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/SystemCall.java new file mode 100644 index 0000000000..5c6c04be21 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/SystemCall.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.os.linux.core.latency; + +import java.io.Serializable; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.tracecompass.segmentstore.core.ISegment; + +import com.google.common.collect.ImmutableMap; + +/** + * A linux kernel system call, represented as an {@link ISegment}. + * + * @author Alexandre Montplaisir + * @since 2.0 + */ +public class SystemCall implements ISegment { + + private static final long serialVersionUID = 1554494342105208730L; + + /** + * The subset of information that is available from the syscall entry event. + */ + public static class InitialInfo implements Serializable { + + private static final long serialVersionUID = -5009710718804983721L; + + private final long fStartTime; + private final String fName; + private final Map fArgs; + + /** + * @param startTime + * Start time of the system call + * @param name + * Name of the system call + * @param arguments + * Arguments of the system call + */ + public InitialInfo( + long startTime, + String name, + Map arguments) { + fStartTime = startTime; + fName = name; + fArgs = ImmutableMap.copyOf(arguments); + } + } + + private final InitialInfo fInfo; + private final long fEndTime; + private final int fRet; + + /** + * @param info + * Initial information of the system call + * @param endTime + * End time of the system call + * @param ret + * Return value of the system call + */ + public SystemCall( + InitialInfo info, + long endTime, + int ret) { + fInfo = info; + fEndTime = endTime; + fRet = ret; + } + + @Override + public long getStart() { + return fInfo.fStartTime; + } + + @Override + public long getEnd() { + return fEndTime; + } + + /** + * Get the name of the system call + * + * @return Name + */ + public String getName() { + return fInfo.fName; + } + + /** + * Get the arguments of the system call + * + * @return Map of the arguments + */ + public Map getArguments() { + return fInfo.fArgs; + } + + /** + * Get the return value of the system call + * + * @return Return value + */ + public int getReturnValue() { + return fRet; + } + + @Override + public int compareTo(@NonNull ISegment o) { + int ret = ISegment.super.compareTo(o); + if (ret != 0) { + return ret; + } + return toString().compareTo(o.toString()); + } + + @Override + public String toString() { + return "Start Time = " + getStart() + //$NON-NLS-1$ + "; End Time = " + getEnd() + //$NON-NLS-1$ + "; Duration = " + getLength() + //$NON-NLS-1$ + "; Name = " + getName() + //$NON-NLS-1$ + "; Args = " + getArguments().toString() + //$NON-NLS-1$ + "; Return = " + getReturnValue(); //$NON-NLS-1$ + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/SystemCallLatencyAnalysis.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/SystemCallLatencyAnalysis.java new file mode 100644 index 0000000000..133a6ea130 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/SystemCallLatencyAnalysis.java @@ -0,0 +1,213 @@ +/******************************************************************************* + * Copyright (c) 2015, 2016 EfficiOS Inc., Ericsson + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.os.linux.core.latency; + +import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelTidAspect; +import org.eclipse.tracecompass.analysis.os.linux.core.tid.TidAnalysisModule; +import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout; +import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace; +import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisEventBasedModule; +import org.eclipse.tracecompass.segmentstore.core.ISegment; +import org.eclipse.tracecompass.segmentstore.core.ISegmentStore; +import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; +import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; +import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +/** + * @author Alexandre Montplaisir + * @since 2.0 + */ +public class SystemCallLatencyAnalysis extends AbstractSegmentStoreAnalysisEventBasedModule { + + /** + * The ID of this analysis + */ + public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.latency.syscall"; //$NON-NLS-1$ + + private static final String DATA_FILENAME = "latency-analysis.dat"; //$NON-NLS-1$ + + private static final Collection BASE_ASPECTS = + ImmutableList.of(SyscallNameAspect.INSTANCE); + + @Override + public String getId() { + return ID; + } + + @Override + protected Iterable getDependentAnalyses() { + ITmfTrace trace = getTrace(); + if (trace == null) { + throw new IllegalStateException(); + } + IAnalysisModule module = trace.getAnalysisModule(TidAnalysisModule.ID); + if (module == null) { + return Collections.EMPTY_SET; + } + return ImmutableSet.of(module); + } + + @Override + public Iterable getSegmentAspects() { + return BASE_ASPECTS; + } + + @Override + public @NonNull String getDataFileName() { + return DATA_FILENAME; + } + + @Override + public AbstractSegmentStoreAnalysisRequest createAnalysisRequest(ISegmentStore syscalls) { + return new SyscallLatencyAnalysisRequest(syscalls); + } + + @Override + protected Object[] readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + return checkNotNull((Object[]) ois.readObject()); + } + + private class SyscallLatencyAnalysisRequest extends AbstractSegmentStoreAnalysisRequest { + + private final Map fOngoingSystemCalls = new HashMap<>(); + private @Nullable IKernelAnalysisEventLayout fLayout; + private final IProgressMonitor fMonitor = new NullProgressMonitor(); + + public SyscallLatencyAnalysisRequest(ISegmentStore syscalls) { + super(syscalls); + } + + @Override + public void handleData(final ITmfEvent event) { + super.handleData(event); + IKernelAnalysisEventLayout layout = fLayout; + if (layout == null) { + IKernelTrace trace = (IKernelTrace) event.getTrace(); + layout = trace.getKernelEventLayout(); + fLayout = layout; + } + final String eventName = event.getType().getName(); + + if (eventName.startsWith(layout.eventSyscallEntryPrefix()) || + eventName.startsWith(layout.eventCompatSyscallEntryPrefix())) { + /* This is a system call entry event */ + + Integer tid; + try { + tid = KernelTidAspect.INSTANCE.resolve(event, true, fMonitor); + } catch (InterruptedException e) { + return; + } + if (tid == null) { + // no information on this event/trace ? + return; + } + + /* Record the event's data into the intial system call info */ + // String syscallName = fLayout.getSyscallNameFromEvent(event); + long startTime = event.getTimestamp().getValue(); + String syscallName = eventName.substring(layout.eventSyscallEntryPrefix().length()); + + Map args = event.getContent().getFieldNames().stream() + .collect(Collectors.toMap(Function.identity(), + input -> checkNotNull(event.getContent().getField(input).toString()))); + + SystemCall.InitialInfo newSysCall = new SystemCall.InitialInfo(startTime, checkNotNull(syscallName), checkNotNull(args)); + fOngoingSystemCalls.put(tid, newSysCall); + + } else if (eventName.startsWith(layout.eventSyscallExitPrefix())) { + /* This is a system call exit event */ + + Integer tid; + try { + tid = KernelTidAspect.INSTANCE.resolve(event, true, fMonitor); + } catch (InterruptedException e) { + return; + } + if (tid == null) { + return; + } + + SystemCall.InitialInfo info = fOngoingSystemCalls.remove(tid); + if (info == null) { + /* + * We have not seen the entry event corresponding to this + * exit (lost event, or before start of trace). + */ + return; + } + + long endTime = event.getTimestamp().getValue(); + int ret = ((Long) event.getContent().getField("ret").getValue()).intValue(); //$NON-NLS-1$ + ISegment syscall = new SystemCall(info, endTime, ret); + getSegmentStore().add(syscall); + } + } + + @Override + public void handleCompleted() { + fOngoingSystemCalls.clear(); + super.handleCompleted(); + } + + @Override + public void handleCancel() { + fMonitor.setCanceled(true); + super.handleCancel(); + } + } + + private static class SyscallNameAspect implements ISegmentAspect { + public static final ISegmentAspect INSTANCE = new SyscallNameAspect(); + + private SyscallNameAspect() { } + + @Override + public String getHelpText() { + return checkNotNull(Messages.SegmentAspectHelpText_SystemCall); + } + @Override + public String getName() { + return checkNotNull(Messages.SegmentAspectName_SystemCall); + } + @Override + public @Nullable Comparator getComparator() { + return null; + } + @Override + public @Nullable String resolve(ISegment segment) { + if (segment instanceof SystemCall) { + return ((SystemCall) segment).getName(); + } + return EMPTY_STRING; + } + } + +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/messages.properties b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/messages.properties new file mode 100644 index 0000000000..f1692c17c1 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/messages.properties @@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2015 Ericsson +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################### + +SegmentAspectName_SystemCall=System Call + +SegmentAspectHelpText_SystemCall=The name of the system call. diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/package-info.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/package-info.java new file mode 100644 index 0000000000..9e258cbba1 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2015 Ericsson + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.eclipse.tracecompass.internal.analysis.os.linux.core.latency; diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/statistics/SystemCallLatencyStatisticsAnalysisModule.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/statistics/SystemCallLatencyStatisticsAnalysisModule.java index 46da158bbe..2b4c1525a2 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/statistics/SystemCallLatencyStatisticsAnalysisModule.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/latency/statistics/SystemCallLatencyStatisticsAnalysisModule.java @@ -13,10 +13,10 @@ package org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.statist import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCall; -import org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCallLatencyAnalysis; import org.eclipse.tracecompass.analysis.timing.core.segmentstore.ISegmentStoreProvider; import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.AbstractSegmentStatisticsAnalysis; +import org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.SystemCall; +import org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.SystemCallLatencyAnalysis; import org.eclipse.tracecompass.segmentstore.core.ISegment; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyTableAnalysisTest.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyTableAnalysisTest.java index 9e29c56866..9a0ab4c5c1 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyTableAnalysisTest.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyTableAnalysisTest.java @@ -17,7 +17,6 @@ import static org.junit.Assert.fail; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Random; @@ -35,10 +34,9 @@ import org.eclipse.swtbot.swt.finder.results.BoolResult; import org.eclipse.swtbot.swt.finder.results.Result; import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable; -import org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCall; -import org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCall.InitialInfo; import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table.AbstractSegmentStoreTableViewer; import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.SystemCallLatencyView; +import org.eclipse.tracecompass.segmentstore.core.BasicSegment; import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace; import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers; import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.SWTBotUtils; @@ -160,9 +158,9 @@ public class SystemCallLatencyTableAnalysisTest { */ @Test public void climbTest() { - List<@NonNull SystemCall> fixture = new ArrayList<>(); + List<@NonNull BasicSegment> fixture = new ArrayList<>(); for (int i = 0; i < 100; i++) { - fixture.add(new SystemCall(new InitialInfo(i, "", Collections.EMPTY_MAP), 2 * i, 0)); + fixture.add(new BasicSegment(i, 2 * i)); } assertNotNull(fTable); @@ -181,9 +179,9 @@ public class SystemCallLatencyTableAnalysisTest { */ @Test public void decrementingTest() { - List<@NonNull SystemCall> fixture = new ArrayList<>(); + List<@NonNull BasicSegment> fixture = new ArrayList<>(); for (int i = 100; i >= 0; i--) { - fixture.add(new SystemCall(new InitialInfo(i, "", Collections.EMPTY_MAP), 2 * i, 0)); + fixture.add(new BasicSegment(i, 2 * i)); } assertNotNull(fTable); fTable.updateModel(fixture); @@ -201,9 +199,9 @@ public class SystemCallLatencyTableAnalysisTest { */ @Test public void smallTest() { - List<@NonNull SystemCall> fixture = new ArrayList<>(); + List<@NonNull BasicSegment> fixture = new ArrayList<>(); for (int i = 1; i >= 0; i--) { - fixture.add(new SystemCall(new InitialInfo(i, "", Collections.EMPTY_MAP), 2 * i, 0)); + fixture.add(new BasicSegment(i, 2 * i)); } assertNotNull(fTable); fTable.updateModel(fixture); @@ -222,9 +220,9 @@ public class SystemCallLatencyTableAnalysisTest { @Test public void largeTest() { final int size = 1000000; - SystemCall[] fixture = new SystemCall[size]; + BasicSegment[] fixture = new BasicSegment[size]; for (int i = 0; i < size; i++) { - fixture[i] = (new SystemCall(new InitialInfo(i, "", Collections.EMPTY_MAP), 2 * i, 0)); + fixture[i] = (new BasicSegment(i, 2 * i)); } assertNotNull(fTable); fTable.updateModel(fixture); @@ -245,11 +243,11 @@ public class SystemCallLatencyTableAnalysisTest { Random rnd = new Random(); rnd.setSeed(1234); final int size = 1000000; - SystemCall[] fixture = new SystemCall[size]; + BasicSegment[] fixture = new BasicSegment[size]; for (int i = 0; i < size; i++) { int start = Math.abs(rnd.nextInt(100000000)); int end = start + Math.abs(rnd.nextInt(1000000)); - fixture[i] = (new SystemCall(new InitialInfo(start, "", Collections.EMPTY_MAP), end, 0)); + fixture[i] = (new BasicSegment(start, end)); } assertNotNull(fTable); fTable.updateModel(fixture); @@ -269,12 +267,12 @@ public class SystemCallLatencyTableAnalysisTest { public void gaussianNoiseTest() { Random rnd = new Random(); rnd.setSeed(1234); - List<@NonNull SystemCall> fixture = new ArrayList<>(); + List<@NonNull BasicSegment> fixture = new ArrayList<>(); for (int i = 1; i <= 1000000; i++) { int start = Math.abs(rnd.nextInt(100000000)); final int delta = Math.abs(rnd.nextInt(1000)); int end = start + delta * delta; - fixture.add(new SystemCall(new InitialInfo(start, "", Collections.EMPTY_MAP), end, 0)); + fixture.add(new BasicSegment(start, end)); } assertNotNull(fTable); fTable.updateModel(fixture); diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml index 2cbb49cc07..fb1abc9d8d 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml @@ -109,28 +109,28 @@ class="org.eclipse.tracecompass.tmf.ui.analysis.TmfAnalysisViewOutput" id="org.eclipse.tracecompass.analysis.os.linux.views.latency"> + class="org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.SystemCallLatencyAnalysis"> + class="org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.SystemCallLatencyAnalysis"> + class="org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.SystemCallLatencyAnalysis"> + class="org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.SystemCallLatencyAnalysis"> fSs; + private final Collection<@NonNull BasicSegment> fSs; /** * Constructor @@ -31,7 +31,7 @@ public class OfflineStatisticsCalculator { * @param ss * segment store, fully build */ - public OfflineStatisticsCalculator(Collection<@NonNull SystemCall> ss) { + public OfflineStatisticsCalculator(Collection<@NonNull BasicSegment> ss) { fSs = ss; } diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/statistics/SegmentStoreStatisticsTest.java b/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/statistics/SegmentStoreStatisticsTest.java index c48a233ac6..893d123248 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/statistics/SegmentStoreStatisticsTest.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/statistics/SegmentStoreStatisticsTest.java @@ -12,14 +12,12 @@ package org.eclipse.tracecompass.analysis.timing.core.tests.segmentstore.statist import static org.junit.Assert.assertEquals; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Random; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCall; -import org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCall.InitialInfo; import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.SegmentStoreStatistics; +import org.eclipse.tracecompass.segmentstore.core.BasicSegment; import org.eclipse.tracecompass.segmentstore.core.ISegment; import org.junit.Test; @@ -42,7 +40,7 @@ public class SegmentStoreStatisticsTest { private static final double NO_ERROR = 0.0; private static final double ERROR = 0.000001; - private static void testOnlineVsOffline(List<@NonNull SystemCall> fixture) { + private static void testOnlineVsOffline(List<@NonNull BasicSegment> fixture) { SegmentStoreStatistics sss = getSegStoreStat(fixture); OfflineStatisticsCalculator osc = new OfflineStatisticsCalculator(fixture); assertEquals("Average", osc.getAvg(), sss.getAverage(), ERROR); @@ -58,9 +56,9 @@ public class SegmentStoreStatisticsTest { */ @Test public void climbTest() { - List<@NonNull SystemCall> fixture = new ArrayList<>(); + List<@NonNull BasicSegment> fixture = new ArrayList<>(); for (int i = 0; i < MEDIUM_AMOUNT_OF_SEGMENTS; i++) { - fixture.add(createAnonSyscall(i, i * 2)); + fixture.add(createDummySegment(i, i * 2)); } SegmentStoreStatistics sss = getSegStoreStat(fixture); assertEquals("Average", 49.5, sss.getAverage(), ERROR); @@ -72,7 +70,7 @@ public class SegmentStoreStatisticsTest { testOnlineVsOffline(fixture); } - private static SegmentStoreStatistics getSegStoreStat(List<@NonNull SystemCall> fixture) { + private static SegmentStoreStatistics getSegStoreStat(List<@NonNull BasicSegment> fixture) { SegmentStoreStatistics sss = new SegmentStoreStatistics(); for (ISegment seg : fixture) { sss.update(seg); @@ -85,9 +83,9 @@ public class SegmentStoreStatisticsTest { */ @Test public void decrementingTest() { - List<@NonNull SystemCall> fixture = new ArrayList<>(); + List<@NonNull BasicSegment> fixture = new ArrayList<>(); for (int i = MEDIUM_AMOUNT_OF_SEGMENTS; i >= 0; i--) { - fixture.add(createAnonSyscall(i, i * 2)); + fixture.add(createDummySegment(i, i * 2)); } SegmentStoreStatistics sss = getSegStoreStat(fixture); assertEquals("Average", 50, sss.getAverage(), NO_ERROR); @@ -104,9 +102,9 @@ public class SegmentStoreStatisticsTest { */ @Test public void smallTest() { - List<@NonNull SystemCall> fixture = new ArrayList<>(); + List<@NonNull BasicSegment> fixture = new ArrayList<>(); for (int i = 1; i >= 0; i--) { - fixture.add(createAnonSyscall(i, i * 2)); + fixture.add(createDummySegment(i, i * 2)); } testOnlineVsOffline(fixture); } @@ -116,9 +114,9 @@ public class SegmentStoreStatisticsTest { */ @Test public void largeTest() { - List<@NonNull SystemCall> fixture = new ArrayList<>(); + List<@NonNull BasicSegment> fixture = new ArrayList<>(); for (int i = 1; i <= LARGE_AMOUNT_OF_SEGMENTS; i++) { - fixture.add(createAnonSyscall(i, i * 2)); + fixture.add(createDummySegment(i, i * 2)); } testOnlineVsOffline(fixture); } @@ -130,11 +128,11 @@ public class SegmentStoreStatisticsTest { public void noiseTest() { Random rnd = new Random(); rnd.setSeed(1234); - List<@NonNull SystemCall> fixture = new ArrayList<>(); + List<@NonNull BasicSegment> fixture = new ArrayList<>(); for (int i = 1; i <= LARGE_AMOUNT_OF_SEGMENTS; i++) { int start = Math.abs(rnd.nextInt(100000000)); int end = start + Math.abs(rnd.nextInt(1000000)); - fixture.add(createAnonSyscall(start, end)); + fixture.add(createDummySegment(start, end)); } testOnlineVsOffline(fixture); } @@ -146,17 +144,17 @@ public class SegmentStoreStatisticsTest { public void gaussianNoiseTest() { Random rnd = new Random(); rnd.setSeed(1234); - List<@NonNull SystemCall> fixture = new ArrayList<>(); + List<@NonNull BasicSegment> fixture = new ArrayList<>(); for (int i = 1; i <= LARGE_AMOUNT_OF_SEGMENTS; i++) { int start = Math.abs(rnd.nextInt(100000000)); final int delta = Math.abs(rnd.nextInt(1000)); int end = start + delta * delta; - fixture.add(createAnonSyscall(start, end)); + fixture.add(createDummySegment(start, end)); } testOnlineVsOffline(fixture); } - private static @NonNull SystemCall createAnonSyscall(int start, int end) { - return new SystemCall(new InitialInfo(start, "", Collections.EMPTY_MAP), end, 0); + private static @NonNull BasicSegment createDummySegment(int start, int end) { + return new BasicSegment(start, end); } }