added capture points to the overhead table

This commit is contained in:
Egor.Ushakov
2017-08-22 12:06:15 +03:00
parent 25a9d4d04f
commit 42f216ce2e
5 changed files with 97 additions and 45 deletions
@@ -28,6 +28,8 @@ import com.intellij.debugger.requests.Requestor;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.debugger.ui.breakpoints.Breakpoint;
import com.intellij.debugger.ui.breakpoints.StackCapturingLineBreakpoint;
import com.intellij.debugger.ui.overhead.OverheadProducer;
import com.intellij.debugger.ui.overhead.OverheadTimings;
import com.intellij.execution.configurations.RemoteConnection;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
@@ -476,6 +478,10 @@ public class DebugProcessEvents extends DebugProcessImpl {
boolean resumePreferred = requestor != null && DebuggerSettings.SUSPEND_NONE.equals(requestor.getSuspendPolicy());
boolean requestHit;
long start = 0;
if (requestor instanceof OverheadProducer) {
start = System.currentTimeMillis();
}
try {
requestHit = (requestor != null) && requestor.processLocatableEvent(this, event);
}
@@ -492,6 +498,11 @@ public class DebugProcessEvents extends DebugProcessImpl {
requestHit = considerRequestHit[0];
resumePreferred = !requestHit;
}
finally {
if (requestor instanceof OverheadProducer) {
OverheadTimings.add(DebugProcessEvents.this, (OverheadProducer)requestor, System.currentTimeMillis() - start);
}
}
if (requestHit && requestor instanceof Breakpoint) {
// if requestor is a breakpoint and this breakpoint was hit, no matter its suspend policy
@@ -33,8 +33,8 @@ import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.debugger.requests.Requestor;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.debugger.ui.overhead.OverheadTimings;
import com.intellij.debugger.ui.impl.watch.CompilingEvaluatorImpl;
import com.intellij.debugger.ui.overhead.OverheadProducer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.project.Project;
@@ -73,7 +73,7 @@ import java.util.Arrays;
import java.util.Objects;
import java.util.function.Function;
public abstract class Breakpoint<P extends JavaBreakpointProperties> implements FilteredRequestor, ClassPrepareRequestor {
public abstract class Breakpoint<P extends JavaBreakpointProperties> implements FilteredRequestor, ClassPrepareRequestor, OverheadProducer {
public static final Key<Breakpoint> DATA_KEY = Key.create("JavaBreakpoint");
private static final Key<Long> HIT_COUNTER = Key.create("HIT_COUNTER");
@@ -223,47 +223,40 @@ public abstract class Breakpoint<P extends JavaBreakpointProperties> implements
@Override
public boolean processLocatableEvent(SuspendContextCommandImpl action, LocatableEvent event) throws EventProcessingException {
long start = System.currentTimeMillis();
SuspendContextImpl context = action.getSuspendContext();
if (!isValid()) {
context.getDebugProcess().getRequestsManager().deleteRequest(this);
return false;
}
String title = DebuggerBundle.message("title.error.evaluating.breakpoint.condition");
try {
String title = DebuggerBundle.message("title.error.evaluating.breakpoint.condition");
try {
StackFrameProxyImpl frameProxy = context.getThread().frame(0);
if (frameProxy == null) {
// might be if the thread has been collected
return false;
}
EvaluationContextImpl evaluationContext = new EvaluationContextImpl(context, frameProxy, () -> getThisObject(context, event));
if (!evaluateCondition(evaluationContext, event)) {
return false;
}
title = DebuggerBundle.message("title.error.evaluating.breakpoint.action");
runAction(evaluationContext, event);
}
catch (final EvaluateException ex) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
System.out.println(ex.getMessage());
return false;
}
throw new EventProcessingException(title, ex.getMessage(), ex);
StackFrameProxyImpl frameProxy = context.getThread().frame(0);
if (frameProxy == null) {
// might be if the thread has been collected
return false;
}
return true;
EvaluationContextImpl evaluationContext = new EvaluationContextImpl(context, frameProxy, () -> getThisObject(context, event));
if (!evaluateCondition(evaluationContext, event)) {
return false;
}
title = DebuggerBundle.message("title.error.evaluating.breakpoint.action");
runAction(evaluationContext, event);
}
finally {
OverheadTimings.add(context.getDebugProcess(), this, System.currentTimeMillis() - start);
catch (final EvaluateException ex) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
System.out.println(ex.getMessage());
return false;
}
throw new EventProcessingException(title, ex.getMessage(), ex);
}
return true;
}
private void runAction(EvaluationContextImpl context, LocatableEvent event) {
@@ -180,6 +180,22 @@ public class StackCapturingLineBreakpoint extends WildcardMethodBreakpoint {
}
}
@Override
public String getDisplayName() {
return "Capture point at " + myCapturePoint.myClassName + "." + myCapturePoint.myMethodName;
}
@Override
public boolean isEnabled() {
return myCapturePoint.myEnabled;
}
@Override
public void setEnabled(boolean enabled) {
myCapturePoint.myEnabled = enabled;
DebuggerSettings.getInstance().setCapturePoints(DebuggerSettings.getInstance().getCapturePoints()); // to fire change event
}
private static void track(DebugProcessImpl debugProcess, CapturePoint capturePoint) {
StackCapturingLineBreakpoint breakpoint = new StackCapturingLineBreakpoint(debugProcess.getProject(), capturePoint);
breakpoint.createRequest(debugProcess);
@@ -0,0 +1,25 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.debugger.ui.overhead;
/**
* @author egor
*/
public interface OverheadProducer {
boolean isEnabled();
void setEnabled(boolean enabled);
String getDisplayName();
}
@@ -15,10 +15,11 @@
*/
package com.intellij.debugger.ui.overhead;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.DebugProcess;
import com.intellij.openapi.util.Key;
import com.intellij.util.EventDispatcher;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EventListener;
import java.util.Map;
@@ -32,30 +33,36 @@ public class OverheadTimings {
public static final Key<OverheadTimings> KEY = Key.create("OVERHEAD_TIMINGS");
private final EventDispatcher<OverheadTimingsListener> myEventDispatcher = EventDispatcher.create(OverheadTimingsListener.class);
private final Map<Object, Timings> myMap = new ConcurrentHashMap<>();
private final Map<OverheadProducer, Timings> myMap = new ConcurrentHashMap<>();
public static long getTime(DebugProcessImpl process, Object producer) {
public static Long getTime(DebugProcess process, OverheadProducer producer) {
Timings timings = getTimings(process).myMap.get(producer);
return timings != null ? timings.myTime : 0;
return timings != null ? timings.myTime : null;
}
public static long getHits(DebugProcessImpl process, Object producer) {
public static long getHits(DebugProcess process, OverheadProducer producer) {
Timings timings = getTimings(process).myMap.get(producer);
return timings != null ? timings.myHits : 0;
}
public static Set<Object> getProducers(DebugProcessImpl process) {
public static Set<OverheadProducer> getProducers(DebugProcess process) {
return getTimings(process).myMap.keySet();
}
public static void add(DebugProcessImpl process, Object producer, long overhead) {
public static void add(DebugProcess process, OverheadProducer producer, @Nullable Long overhead) {
OverheadTimings timings = getTimings(process);
timings.myMap.merge(producer, new Timings(1, overhead), (old, value) -> new Timings(old.myHits + 1, old.myTime + overhead));
timings.myMap.merge(producer, new Timings(1, overhead), (old, value) -> {
Long newTime = old.myTime;
if (value.myTime != null) {
newTime += value.myTime;
}
return new Timings(old.myHits + 1, newTime);
});
timings.myEventDispatcher.getMulticaster().timingAdded(producer);
}
@NotNull
private static OverheadTimings getTimings(DebugProcessImpl process) {
private static OverheadTimings getTimings(DebugProcess process) {
OverheadTimings data = process.getUserData(KEY);
if (data == null) {
data = new OverheadTimings();
@@ -66,19 +73,19 @@ public class OverheadTimings {
private static class Timings {
final long myHits;
final long myTime;
final Long myTime;
public Timings(long hits, long time) {
public Timings(long hits, Long time) {
myHits = hits;
myTime = time;
}
}
static void addListener(OverheadTimingsListener listener, DebugProcessImpl process) {
static void addListener(OverheadTimingsListener listener, DebugProcess process) {
getTimings(process).myEventDispatcher.addListener(listener);
}
public interface OverheadTimingsListener extends EventListener {
void timingAdded(Object producer);
void timingAdded(OverheadProducer producer);
}
}