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

[JFXPanel] High JFXPanel CPU usage at high resolutions

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • tbd
    • 7u55, 8u5
    • javafx
    • Red Hat Enterprise Linux 6.2
      Xorg 1.10.4
      Gnome 2.28.2
      nVidia Quadro 410 driver rev. 331.79
      Intel Xeon E5-1630

      Our application runs as a JFXPanel in a full screen JFrame with legacy Swing dialogue windows on linux.

      When the application is run on high resolution screens (EG 2560x1440) the CPU load on the AWT EDT is noticeably higher. This is somewhat expected as the JFXPanel is forced to transfer more pixels at higher resolutions however it ties up the AWT EDT which can cause problems with legacy swing features.

      Internally the JFXPanel uses a BufferedImage created using the BufferedImage constructor to store the pixels being transferred between JavaFX and Swing.
      Changing the JFXPanel to create this BufferedImage using GraphicsConfiguration.createCompatibleImage can result in lower CPU load on the AWT EDT.

      Using the example application below which updates the JavaFX scene at 10 Hz the following results were measured on linux.

       - JDK7u55 BufferedImage constructor : 45% of one CPU core consumed by EDT
       - JDK7u55 createCompatibleImage : 18.5% of one CPU core consumed by EDT
       - JDK8u5 BufferedImage constructor : 24% of one CPU core consumed by EDT
       - JDK8u5 createCompatibleImage : 10.5% of one CPU core consumed by EDT

      The X11 configuration generated by xdpyinfo is as follows:
      name of display: :0.0
      version number: 11.0
      vendor string: Red Hat, Inc.
      vendor release number: 11004000
      maximum request size: 16777212 bytes
      motion buffer size: 256
      bitmap unit, bit order, padding: 32, LSBFirst, 32
      image byte order: LSBFirst
      number of supported pixmap formats: 7
      supported pixmap formats:
          depth 1, bits_per_pixel 1, scanline_pad 32
          depth 4, bits_per_pixel 8, scanline_pad 32
          depth 8, bits_per_pixel 8, scanline_pad 32
          depth 15, bits_per_pixel 16, scanline_pad 32
          depth 16, bits_per_pixel 16, scanline_pad 32
          depth 24, bits_per_pixel 32, scanline_pad 32
          depth 32, bits_per_pixel 32, scanline_pad 32
      keycode range: minimum 8, maximum 255
      focus: PointerRoot
      number of extensions: 28
          BIG-REQUESTS
          Composite
          DAMAGE
          DOUBLE-BUFFER
          DPMS
          DRI2
          GLX
          Generic Event Extension
          MIT-SCREEN-SAVER
          MIT-SHM
          NV-CONTROL
          NV-GLX
          RANDR
          RECORD
          RENDER
          SHAPE
          SYNC
          X-Resource
          XC-MISC
          XFIXES
          XFree86-DGA
          XFree86-VidModeExtension
          XINERAMA
          XINERAMA
          XInputExtension
          XKEYBOARD
          XTEST
          XVideo
      default screen number: 0
      number of screens: 1

      screen #0:
        print screen: no
        dimensions: 2560x1440 pixels (602x341 millimeters)
        resolution: 108x107 dots per inch
        depths (7): 24, 1, 4, 8, 15, 16, 32
        root window id: 0x2f2
        depth of root window: 24 planes
        number of colormaps: minimum 1, maximum 1
        default colormap: 0x20
        default number of colormap cells: 256
        preallocated pixels: black 0, white 16777215
        options: backing-store YES, save-unders NO
        largest cursor: 256x256
        current input event mask: 0x0
        number of visuals: 276
        default visual id: 0x21
        visual:
          visual id: 0x21
          class: TrueColor
          depth: 24 planes
          available colormap entries: 256 per subfield
          red, green, blue masks: 0xff0000, 0xff00, 0xff
          significant bits in color specification: 14 bits
        visual:
          visual id: 0x22
          class: DirectColor
          depth: 24 planes
          available colormap entries: 256 per subfield
          red, green, blue masks: 0xff0000, 0xff00, 0xff
          significant bits in color specification: 14 bits
      .....

      The following sample application updates a full screen JFXPanel at 10 Hz and was used to produce the figures above:

      import java.awt.HeadlessException;
      import java.text.SimpleDateFormat;
      import java.util.Date;

      import javafx.animation.AnimationTimer;
      import javafx.application.Platform;
      import javafx.embed.swing.JFXPanel;
      import javafx.scene.Scene;
      import javafx.scene.control.Label;
      import javafx.scene.layout.BorderPane;

      import javax.swing.JFrame;

      public class JFXPanelTest extends JFrame {

          private Label timeLabel;

          public JFXPanelTest() throws HeadlessException {
              super("JFXPanel Test");
              setUndecorated(true);
              setExtendedState(JFrame.MAXIMIZED_BOTH);
              final JFXPanel fxPanel = new JFXPanel();
              add(fxPanel);
              Platform.runLater(new Runnable() {
                  @Override
                  public void run() {
                      fxPanel.setScene(buildScene());
                  }
              });
          }

          private Scene buildScene() {
              BorderPane fxContent = new BorderPane();
              timeLabel = new Label();
              fxContent.centerProperty().set(timeLabel);
              ClockTimer clockTimer = new ClockTimer();
              clockTimer.start();
              return new Scene(fxContent);
          }

          public static void main(String[] args) {
              JFXPanelTest fxPanelTest = new JFXPanelTest();
              fxPanelTest.setDefaultCloseOperation(EXIT_ON_CLOSE);
              fxPanelTest.setVisible(true);
          }

          private class ClockTimer extends AnimationTimer {

              private SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.S");
              private String previousTime;

              @Override
              public void handle(long arg0) {
                  String currentTime = dateFormat.format(new Date());
                  // truncate to tenths of a second
                  currentTime = currentTime.substring(0, currentTime.length() - 2);
                  if (!currentTime.equals(previousTime)) {
                      timeLabel.setText(currentTime);
                      previousTime = currentTime;
                  }
              }
          }
      }

            psadhukhan Prasanta Sadhukhan
            duke J. Duke
            Votes:
            2 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: