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

JavaFX charts peg rendering thread as more data is added

    XMLWordPrintable

Details

    • x86_64
    • generic

    Description

      FULL PRODUCT VERSION :
      java version "1.8.0_121"
      Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Linux 4.4.0-83-generic #106-Ubuntu SMP Mon Jun 26 17:54:43 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      AreaCharts and LineCharts quickly peg the rendering thread with large, updating data series. How quickly the thread is pegged depends on how many data points there are, regardless of the visible area of the chart and independent of the update rate; a 2Hz update rate will still peg the rendering thread, just not as quickly as at 50Hz or 100Hz.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Update a line or area chart with data from a real-time stream (see the SSCCE).

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The UI should remain snappy and responsive
      ACTUAL -
      The UI responsiveness becomes more and more sluggish as more data is added.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import javafx.application.Application;
      import javafx.application.Platform;
      import javafx.scene.Scene;
      import javafx.scene.chart.AreaChart;
      import javafx.scene.chart.NumberAxis;
      import javafx.scene.chart.XYChart;
      import javafx.scene.control.Button;
      import javafx.scene.control.Slider;
      import javafx.scene.layout.StackPane;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;

      import java.util.concurrent.Executors;
      import java.util.concurrent.ThreadFactory;
      import java.util.concurrent.TimeUnit;

      public class SlowCharts extends Application {

        private int dataNum = 0;

        private static final ThreadFactory daemonThreadFactory = r -> {
          Thread t = new Thread(r);
          t.setDaemon(true);
          return t;
        };

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

        @Override
        public void start(Stage primaryStage) throws Exception {

          final double WINDOW_SIZE = 150; // show ~5 seconds worth of data points

          NumberAxis xAxis = new NumberAxis("", 0, WINDOW_SIZE, 30);
          NumberAxis yAxis = new NumberAxis("", 0, 1, 0.5);
          xAxis.lowerBoundProperty().bind(xAxis.upperBoundProperty().subtract(WINDOW_SIZE));

          XYChart.Series<Number, Number> series = new XYChart.Series<>();
          series.setName("Data");

          AreaChart<Number, Number> chart = new AreaChart<>(xAxis, yAxis);
          chart.setAnimated(false);
          chart.setCreateSymbols(false);
          chart.getData().add(series);

          // Add new data approximately 30 times per second
          // This can be sped up to cause a more rapid loss of responsiveness
          Executors.newSingleThreadScheduledExecutor(daemonThreadFactory)
                   .scheduleAtFixedRate(() -> {
                     Platform.runLater(() -> {
                       series.getData().add(new XYChart.Data<>(dataNum++, Math.random()));
                       xAxis.setUpperBound(dataNum);
                     });
                   }, 100, 33, TimeUnit.MILLISECONDS);

          // A "clear" button to confirm that the sluggishness is caused by the amount of data in the chart
          Button clearButton = new Button("Clear");
          clearButton.setOnAction(e -> {
            series.getData().clear();
            dataNum = 0;
          });

          // Add a slider to test UI responsiveness
          primaryStage.setScene(new Scene(new VBox(new StackPane(chart), new Slider(-1, 1, 0), clearButton)));
          primaryStage.show();
        }

      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Remove data from series that is outside the range of the X-axis, but requires two copies of the data and still has problems with large ranges on the X-axis.

      Smoothing the data to remove points also helps, but requires clearing and setting the data in the series which becomes a problem with large amounts of data.

      Attachments

        Issue Links

          Activity

            People

              flar Jim Graham
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: