Improve java debug performance to fetch list of threads/frames/variables (#10492)
* Improve debug performance Signed-off-by: Anatoliy Bazko <abazko@redhat.com>6.19.x
parent
88add6e333
commit
0b86fa358b
|
|
@ -181,4 +181,13 @@ public interface DebuggerServiceClient {
|
|||
* @param frameIndex the frame index inside the thread
|
||||
*/
|
||||
Promise<String> evaluate(String id, String expression, long threadId, int frameIndex);
|
||||
|
||||
/**
|
||||
* Gets a location of the resources for the given frame.
|
||||
*
|
||||
* @param id debug session id
|
||||
* @param threadId the unique thread id {@link ThreadState#getId()}
|
||||
* @param frameIndex the frame index inside the thread
|
||||
*/
|
||||
Promise<LocationDto> getStackFrameLocation(String id, long threadId, int frameIndex);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,6 +208,15 @@ public class DebuggerServiceClientImpl implements DebuggerServiceClient {
|
|||
.send(new StringUnmarshaller());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<LocationDto> getStackFrameLocation(String id, long threadId, int frameIndex) {
|
||||
String requestUrl = getBaseUrl(id) + "/location?thread=" + threadId + "&frame=" + frameIndex;
|
||||
return asyncRequestFactory
|
||||
.createGetRequest(requestUrl)
|
||||
.loader(loaderFactory.newLoader())
|
||||
.send(dtoUnmarshallerFactory.newUnmarshaller(LocationDto.class));
|
||||
}
|
||||
|
||||
private String getBaseUrl(String id) {
|
||||
final String url = appContext.getWsAgentServerApiEndpoint() + "/debugger";
|
||||
if (id != null) {
|
||||
|
|
|
|||
|
|
@ -125,6 +125,14 @@ public interface Debugger extends DebuggerObservable {
|
|||
*/
|
||||
void setValue(Variable variable, long threadId, int frameIndex);
|
||||
|
||||
/**
|
||||
* Gets a location of the resources for the given frame.
|
||||
*
|
||||
* @param threadId the unique thread id {@link ThreadState#getId()}
|
||||
* @param frameIndex the frame index inside the thread
|
||||
*/
|
||||
Promise<? extends Location> getStackFrameLocation(long threadId, int frameIndex);
|
||||
|
||||
/** Indicates if connection is established with the server. */
|
||||
boolean isConnected();
|
||||
|
||||
|
|
|
|||
|
|
@ -709,6 +709,15 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<? extends Location> getStackFrameLocation(long threadId, int frameIndex) {
|
||||
if (isConnected()) {
|
||||
return service.getStackFrameLocation(debugSessionDto.getId(), threadId, frameIndex);
|
||||
}
|
||||
|
||||
return promiseProvider.reject(JsPromiseError.create("Debugger is not connected"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return debugSessionDto != null;
|
||||
|
|
|
|||
|
|
@ -214,7 +214,18 @@ public class DebuggerPresenter extends BasePresenter
|
|||
if (threadState != null) {
|
||||
List<? extends StackFrameDump> frames = threadState.getFrames();
|
||||
if (frames.size() > frameIndex) {
|
||||
open(frames.get(frameIndex).getLocation());
|
||||
|
||||
Debugger debugger = debuggerManager.getActiveDebugger();
|
||||
if (debugger != null && debugger.isSuspended()) {
|
||||
debugger
|
||||
.getStackFrameLocation(threadId, frameIndex)
|
||||
.then(
|
||||
location -> {
|
||||
if (isSameSelection(threadId, frameIndex)) {
|
||||
open(location);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ import org.eclipse.che.plugin.jdb.server.expression.Evaluator;
|
|||
import org.eclipse.che.plugin.jdb.server.expression.ExpressionException;
|
||||
import org.eclipse.che.plugin.jdb.server.expression.ExpressionParser;
|
||||
import org.eclipse.che.plugin.jdb.server.model.JdbLocation;
|
||||
import org.eclipse.che.plugin.jdb.server.model.JdbMethod;
|
||||
import org.eclipse.che.plugin.jdb.server.model.JdbStackFrame;
|
||||
import org.eclipse.che.plugin.jdb.server.utils.JavaDebuggerUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -405,8 +404,7 @@ public class JavaDebugger implements EventsHandler, Debugger {
|
|||
List<JdbStackFrame> frames = new LinkedList<>();
|
||||
try {
|
||||
for (StackFrame f : t.frames()) {
|
||||
frames.add(
|
||||
new JdbStackFrame(f, emptyList(), emptyList(), new JdbLocation(f, new JdbMethod(f))));
|
||||
frames.add(new JdbStackFrame(f, emptyList(), emptyList()));
|
||||
}
|
||||
} catch (IncompatibleThreadStateException ignored) {
|
||||
// Thread isn't suspended. Information isn't available.
|
||||
|
|
@ -424,6 +422,7 @@ public class JavaDebugger implements EventsHandler, Debugger {
|
|||
|
||||
return threadStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value of variable with specified path. Each item in path is name of variable.
|
||||
*
|
||||
|
|
@ -722,6 +721,12 @@ public class JavaDebugger implements EventsHandler, Debugger {
|
|||
return result == null ? "null" : result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getStackFrameLocation(long threadId, int frameIndex) throws DebuggerException {
|
||||
StackFrame jdiStackFrame = getJdiStackFrame(threadId, frameIndex);
|
||||
return new JdbLocation(jdiStackFrame);
|
||||
}
|
||||
|
||||
private com.sun.jdi.Value evaluate(ExpressionParser parser, long threadId, int frameIndex)
|
||||
throws DebuggerException {
|
||||
StackFrame jdiStackFrame = getJdiStackFrame(threadId, frameIndex);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,12 @@ public class JdbLocation implements Location {
|
|||
this(stackFrame, new JdbMethod(stackFrame));
|
||||
}
|
||||
|
||||
public JdbLocation(Location internal, Method method) {
|
||||
this.method = method;
|
||||
this.internal = internal;
|
||||
this.jdiStackFrame = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intends to create location when thread is not suspended. Information concerning thread and
|
||||
* frame are not available.
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import org.eclipse.che.api.debug.shared.model.Field;
|
|||
import org.eclipse.che.api.debug.shared.model.Location;
|
||||
import org.eclipse.che.api.debug.shared.model.StackFrameDump;
|
||||
import org.eclipse.che.api.debug.shared.model.Variable;
|
||||
import org.eclipse.che.api.debug.shared.model.impl.LocationImpl;
|
||||
import org.eclipse.che.api.debug.shared.model.impl.VariablePathImpl;
|
||||
|
||||
/**
|
||||
|
|
@ -38,20 +39,28 @@ public class JdbStackFrame implements StackFrameDump {
|
|||
|
||||
public JdbStackFrame(com.sun.jdi.StackFrame jdiStackFrame) {
|
||||
this.jdiStackFrame = jdiStackFrame;
|
||||
this.location = new JdbLocation(jdiStackFrame);
|
||||
|
||||
com.sun.jdi.Location jdiLocation = jdiStackFrame.location();
|
||||
this.location =
|
||||
new JdbLocation(
|
||||
new LocationImpl(jdiLocation.declaringType().name(), jdiLocation.lineNumber()),
|
||||
new JdbMethod(jdiStackFrame));
|
||||
|
||||
this.variables = new AtomicReference<>();
|
||||
this.fields = new AtomicReference<>();
|
||||
}
|
||||
|
||||
public JdbStackFrame(
|
||||
com.sun.jdi.StackFrame jdiStackFrame,
|
||||
List<Field> fields,
|
||||
List<Variable> variables,
|
||||
Location location) {
|
||||
com.sun.jdi.StackFrame jdiStackFrame, List<Field> fields, List<Variable> variables) {
|
||||
this.jdiStackFrame = jdiStackFrame;
|
||||
this.fields = new AtomicReference<>(fields);
|
||||
this.variables = new AtomicReference<>(variables);
|
||||
this.location = location;
|
||||
|
||||
com.sun.jdi.Location jdiLocation = jdiStackFrame.location();
|
||||
this.location =
|
||||
new JdbLocation(
|
||||
new LocationImpl(jdiLocation.declaringType().name(), jdiLocation.lineNumber()),
|
||||
new JdbMethod(jdiStackFrame));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public class StackFrameDumpTest1 {
|
|||
|
||||
LocationDto location = stackFrame.getLocation();
|
||||
assertEquals(location.getLineNumber(), 25);
|
||||
assertEquals(location.getTarget(), "/test/src/org/eclipse/StackFrameDumpTest1.java");
|
||||
assertEquals(location.getTarget(), "org.eclipse.StackFrameDumpTest1");
|
||||
|
||||
MethodDto method = location.getMethod();
|
||||
assertEquals(method.getName(), "do2");
|
||||
|
|
@ -134,7 +134,7 @@ public class StackFrameDumpTest1 {
|
|||
|
||||
LocationDto location = stackFrame.getLocation();
|
||||
assertEquals(location.getLineNumber(), 21);
|
||||
assertEquals(location.getTarget(), "/test/src/org/eclipse/StackFrameDumpTest1.java");
|
||||
assertEquals(location.getTarget(), "org.eclipse.StackFrameDumpTest1");
|
||||
|
||||
MethodDto method = location.getMethod();
|
||||
assertEquals(method.getName(), "do1");
|
||||
|
|
@ -188,7 +188,7 @@ public class StackFrameDumpTest1 {
|
|||
|
||||
LocationDto location = stackFrame.getLocation();
|
||||
assertEquals(location.getLineNumber(), 16);
|
||||
assertEquals(location.getTarget(), "/test/src/org/eclipse/StackFrameDumpTest1.java");
|
||||
assertEquals(location.getTarget(), "org.eclipse.StackFrameDumpTest1");
|
||||
|
||||
MethodDto method = location.getMethod();
|
||||
assertEquals(method.getName(), "main");
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ public class ThreadDumpTest1 {
|
|||
|
||||
Location location = stackFrameDump.getLocation();
|
||||
assertEquals(location.getLineNumber(), 26);
|
||||
assertEquals(location.getTarget(), "/test/src/org/eclipse/ThreadDumpTest1.java");
|
||||
assertEquals(location.getExternalResourceId(), -1);
|
||||
assertEquals(location.getResourceProjectPath(), "/test");
|
||||
assertEquals(location.getTarget(), "org.eclipse.ThreadDumpTest1");
|
||||
assertEquals(location.getExternalResourceId(), 0);
|
||||
assertNull(location.getResourceProjectPath());
|
||||
|
||||
Method method = location.getMethod();
|
||||
assertEquals(method.getName(), "main");
|
||||
|
|
|
|||
|
|
@ -97,15 +97,15 @@ public class ThreadDumpTest {
|
|||
|
||||
String[] frames = debugPanel.getFrames();
|
||||
assertEquals(frames.length, 1);
|
||||
assertTrue(frames[0].contains("main(String[]):19, App"));
|
||||
assertTrue(frames[0].contains("main(String[]):19, multimodule.App"));
|
||||
|
||||
debugPanel.clickOnButton(DebugPanel.DebuggerActionButtons.RESUME_BTN_ID);
|
||||
debugPanel.waitDebugHighlightedText("this.title = title;");
|
||||
|
||||
frames = debugPanel.getFrames();
|
||||
assertEquals(frames.length, 2);
|
||||
assertTrue(frames[0].contains("<init>(String, String):18, BookImpl"));
|
||||
assertTrue(frames[1].contains("main(String[]):19, App"));
|
||||
assertTrue(frames[0].contains("<init>(String, String):18, multimodule.model.BookImpl"));
|
||||
assertTrue(frames[1].contains("main(String[]):19, multimodule.App"));
|
||||
|
||||
editor.closeAllTabs();
|
||||
|
||||
|
|
|
|||
|
|
@ -244,6 +244,19 @@ public interface Debugger {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a location of the resources for the given frame.
|
||||
*
|
||||
* @throws DebuggerException if any error occur
|
||||
*/
|
||||
default Location getStackFrameLocation(long threadId, int frameIndex) throws DebuggerException {
|
||||
if (threadId == -1) {
|
||||
return dumpStackFrame().getLocation();
|
||||
}
|
||||
|
||||
return getStackFrameDump(threadId, frameIndex).getLocation();
|
||||
}
|
||||
|
||||
/** Is used to send back any events to client. */
|
||||
interface DebuggerCallback {
|
||||
void onEvent(DebuggerEvent event);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import javax.ws.rs.core.MultivaluedMap;
|
|||
import javax.ws.rs.core.UriInfo;
|
||||
import org.eclipse.che.api.debug.shared.dto.BreakpointDto;
|
||||
import org.eclipse.che.api.debug.shared.dto.DebugSessionDto;
|
||||
import org.eclipse.che.api.debug.shared.dto.LocationDto;
|
||||
import org.eclipse.che.api.debug.shared.dto.SimpleValueDto;
|
||||
import org.eclipse.che.api.debug.shared.dto.StackFrameDumpDto;
|
||||
import org.eclipse.che.api.debug.shared.dto.ThreadStateDto;
|
||||
|
|
@ -197,6 +198,18 @@ public class DebuggerService {
|
|||
return threadStates.stream().map(DtoConverter::asDto).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/location")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public LocationDto getStackFrameLocation(
|
||||
@PathParam("id") String sessionId,
|
||||
@QueryParam("thread") @DefaultValue("-1") long threadId,
|
||||
@QueryParam("frame") @DefaultValue("-1") int frameIndex)
|
||||
throws DebuggerException {
|
||||
return DtoConverter.asDto(
|
||||
debuggerManager.getDebugger(sessionId).getStackFrameLocation(threadId, frameIndex));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/value")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
|
|
|
|||
Loading…
Reference in New Issue