I'm writing a test application that displays an A* search in action, and it's running really slow. I profiled it using VisualVM, and got the following results:
Note that the third entry is a lambda containing some long-running code.
The problem is, I can't find a lambda with such a signature anywhere.
Is there any way for me to find out what lambda it's referring to?
Here is pacmanTest.FrontierVisual.java
:
package pacmanTest;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import utils.Duple;
import utils.MainLoop;
public class FrontierVisual
extends Application {
private Stage stage;
private Scene scene;
private final int areaWidth = 800;
private final int areaHeight = 800;
private final double drawScale = 15;
private Canvas canvas = new Canvas(800, 800);
private GraphicsContext gc = canvas.getGraphicsContext2D();
private final MapArea<Wall> area = new MapArea<>(areaWidth, areaHeight);
private static List<Duple<Integer>> cellsAround(Duple<Integer> pos, List<Duple<Integer>> offsets) {
List<Duple<Integer>> surroundingCells = new ArrayList<>();
offsets.stream()
.map( offset -> pos.map(offset, (x1, x2) -> x1 + x2) )
.forEach(surroundingCells::add);
return surroundingCells;
}
private void drawSquare(Duple<Integer> position, Color color) {
gc.setFill(color);
gc.fillRect(position.getX() * drawScale, position.getY() * drawScale, drawScale, drawScale);
}
@Override
public void start(Stage stage) throws Exception {
this.stage = stage;
BorderPane rootNode = new BorderPane();
scene = new Scene(rootNode);
stage.setScene(scene);
rootNode.setCenter(canvas);
Duple<Integer> startPos = new Duple<Integer>(20, 20);
Duple<Integer> goalPos = new Duple<Integer>(30, 30);
Wall wall = new SolidWall();
/*for (int d = 29; d <= 41; d++) {
int e = d / 2;
area.setCellAt(d, e, wall);
}*/
area.setCellAt(19, 32, wall);
area.setCellAt(20, 31, wall);
area.setCellAt(21, 30, wall);
area.setCellAt(22, 29, wall);
area.setCellAt(23, 28, wall);
area.setCellAt(24, 27, wall);
area.setCellAt(25, 26, wall);
area.setCellAt(26, 25, wall);
area.setCellAt(27, 24, wall);
area.setCellAt(28, 23, wall);
area.setCellAt(29, 22, wall);
area.setCellAt(30, 21, wall);
area.setCellAt(31, 20, wall);
area.setCellAt(32, 19, wall);
Deque<Duple<Integer>> frontier = new ArrayDeque<>();
Map<Duple<Integer>, Duple<Integer>> cameFrom = new HashMap<>();
cameFrom.put(startPos, startPos);
frontier.push(startPos);
final List<Duple<Integer>> fourDirectionOffsets = Collections.unmodifiableList(Arrays.asList(
new Duple<Integer>(1,0), new Duple<Integer>(-1,0), new Duple<Integer>(0,1), new Duple<Integer>(0,-1) ));
MainLoop mainLoop = new MainLoop(10000, t -> {
utils.Utils.clearCanvas(gc);
gc.setFill(Color.STEELBLUE);
Duple<Integer> poppedLocation = frontier.pop();
drawSquare(startPos, Color.BLACK);
drawSquare(goalPos, Color.GREEN);
List<Duple<Integer>> neighbors = cellsAround(poppedLocation, fourDirectionOffsets);
neighbors.stream()
.filter(location -> !cameFrom.containsKey(location) && area.cellIsInBounds(location) && area.getCellAt(location) == null)
.forEach( neighbor -> {
frontier.add(neighbor);
cameFrom.put(neighbor, poppedLocation);
drawSquare(neighbor, Color.CORAL);
});
frontier.stream()
.forEach( frontierPos -> {
drawSquare(frontierPos, Color.BLUE);
});
reconstructPath(cameFrom, startPos, goalPos).stream()
.forEach( pathPos -> {
if (pathPos != startPos && area.getCellAt(pathPos) == null) {
drawSquare(pathPos, Color.ORANGE);
}
});
area.forallNonEmptyCells( (pos, contents) -> {
drawSquare(pos, Color.CHOCOLATE);
});
});
mainLoop.start();
stage.show();
}
private static List<Duple<Integer>> reconstructPath(Map<Duple<Integer>, Duple<Integer>> cameFrom, Duple<Integer> start, Duple<Integer> goal) {
List<Duple<Integer>> path = new ArrayList<>();
path.add(goal);
Duple<Integer> current = goal;
do {
path.add(current);
current = cameFrom.get(current);
} while (current != null && !current.equals(start));
Collections.reverse(path);
return path;
}
public static void main(String[] args) {
launch(args);
}
}
Any ideas here would be appreciated.
Side note: If anyone knows how to reduce the drawing time of JavaFX's canvas, that would be awesome given it's the biggest CPU hog.