From 42f216ce2e873536cc1700c1694d19c8cfdeefec Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 22 Aug 2017 11:57:47 +0300 Subject: [PATCH] added capture points to the overhead table --- .../debugger/engine/DebugProcessEvents.java | 11 ++++ .../debugger/ui/breakpoints/Breakpoint.java | 57 ++++++++----------- .../StackCapturingLineBreakpoint.java | 16 ++++++ .../ui/overhead/OverheadProducer.java | 25 ++++++++ .../debugger/ui/overhead/OverheadTimings.java | 33 ++++++----- 5 files changed, 97 insertions(+), 45 deletions(-) create mode 100644 java/debugger/impl/src/com/intellij/debugger/ui/overhead/OverheadProducer.java diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java index fe9c056a436d..dc11655fb4e3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java @@ -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 diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java index 7ee002caf789..423a8f537672 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java @@ -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

implements FilteredRequestor, ClassPrepareRequestor { +public abstract class Breakpoint

implements FilteredRequestor, ClassPrepareRequestor, OverheadProducer { public static final Key DATA_KEY = Key.create("JavaBreakpoint"); private static final Key HIT_COUNTER = Key.create("HIT_COUNTER"); @@ -223,47 +223,40 @@ public abstract class Breakpoint

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) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java index e23da2fbbd25..a23a7ac6fbe9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java @@ -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); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/overhead/OverheadProducer.java b/java/debugger/impl/src/com/intellij/debugger/ui/overhead/OverheadProducer.java new file mode 100644 index 000000000000..a79ad0f31475 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/ui/overhead/OverheadProducer.java @@ -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(); +} diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/overhead/OverheadTimings.java b/java/debugger/impl/src/com/intellij/debugger/ui/overhead/OverheadTimings.java index aff39c23c71b..d126a1f4fbad 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/overhead/OverheadTimings.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/overhead/OverheadTimings.java @@ -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 KEY = Key.create("OVERHEAD_TIMINGS"); private final EventDispatcher myEventDispatcher = EventDispatcher.create(OverheadTimingsListener.class); - private final Map myMap = new ConcurrentHashMap<>(); + private final Map 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 getProducers(DebugProcessImpl process) { + public static Set 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); } }