Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8367064

Performance degradation - ImagePools locked cache grows when using cached node

XMLWordPrintable

    • x86_64
    • windows

      ADDITIONAL SYSTEM INFORMATION :
      Windows 11, D3D Rendering Pipeliine

      A DESCRIPTION OF THE PROBLEM :
      When nodes with setCache(true) are used in the scene graph, the ImagePool will create a new Image via renderer.createCompatibleImage(w, h) and add it (with a SoftReferene) to its 'locked' list. This list can grow over time. But even if the original nodes are not available anymore and are GC'ed, the elements stay in that locked list.
      This can lead to a severe performance degredation, showing up over time in form of reduced frames per second, as this list is beeing iterated over very often.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      I put some debug outputs in the ImagePool class:
      - in checkOut around line 165:
      // get rid of expired entries from locked list
      System.out.println("check OUT - locked size: " + this.locked.size());
      entries = this.locked.iterator();
      - in checkIn around line 200:
      System.out.println("check IN - locked size: " + this.locked.size());
      Iterator<SoftReference<PoolFilterable>> entries = this.locked.iterator();

      Run Demo Application from below (Test Case Code).

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The output showing at some point in time that the locked list has only a few elements in it.
      ACTUAL -
      The element size of the locked list grows indefinite. The system output shows:
      check OUT - locked size: 0
      check OUT - locked size: 1
      check OUT - locked size: 2
      check OUT - locked size: 3
      check OUT - locked size: 4
      cleared
      check OUT - locked size: 5
      check OUT - locked size: 6
      check OUT - locked size: 7
      check OUT - locked size: 8
      check OUT - locked size: 9
      cleared
      check OUT - locked size: 10
      check OUT - locked size: 11
      .......

      ---------- BEGIN SOURCE ----------
      public class Main extends Application {

      @Override
      public void start(Stage primaryStage) {

      final var root = new BorderPane();
      final var scene = new Scene(root, 400, 400);
      primaryStage.setScene(scene);
      primaryStage.show();

      final var scheduledExecService = Executors.newScheduledThreadPool(1);

      scheduledExecService.scheduleAtFixedRate(() -> {
      final var region = new Region();
      region.setStyle("-fx-background-color: red;");
      region.setCache(true);

      Platform.runLater(() -> root.setCenter(region));

      }, 1L, 1L, TimeUnit.SECONDS);

      scheduledExecService.scheduleAtFixedRate(() -> {
      Platform.runLater(() -> {
      root.getChildren().clear();
      System.gc();
      System.out.println("cleared");
      });

      }, 5500L, 5000L, TimeUnit.MILLISECONDS);
      }

      public static void main(String[] args) {
      launch(args);
      }
      }
      ---------- END SOURCE ----------

            kcr Kevin Rushforth
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: