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

Text rendering has slow initialization time

XMLWordPrintable

    • 2d
    • x86
    • os_x

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

      java version "9-ea"
      Java(TM) SE Runtime Environment (build 9-ea+166)
      Java HotSpot(TM) 64-Bit Server VM (build 9-ea+166, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      macOS Sierra 10.12.4

      A DESCRIPTION OF THE PROBLEM :
      Rendering text for the first time using GraphicContext.drawString or retrieving FontMetrics for the first time results in a long delay.

      Both actions above will result in call to java.awt.Font.getFont2D() which ultimately calls a loadNativeFonts() method.

      The delay is 2-3 seconds for both java 8 and java 9.

      Applications that do not render text take about 1/5 the time to display results.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      The included source code shows timings for displaying a window with and without text.

      1) Run as is (NoText)
          - baseline: renders graphics without text

      2) Run with just Text() uncommented
          - Example 1: renders text causing a delay in output (2-3s)

      3) Run with just TextAfter() uncommented
          - Example 2: renders graphics without text immediately, loads FontMetrics concurrently, once loading is done text rendering occurs with little / no delay.

      The delay observed in #2 (DrawString) is about the same as the delay in #3 (getFontMetrics). Profiling shows sun.font.CFontManager.loadNativeFonts() takes most of this time.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Graphical displays without text rendering occurs sub-second after the JVM has been launched at least once. Keeping the response time sub-second with text rendering is desirable.
      ACTUAL -
      Windows appear frozen / blank for 2-3 seconds when first launched if any text is rendered to the screen.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package bugreport;

      import java.awt.Color;
      import java.awt.Component;
      import java.awt.Graphics;
      import java.awt.image.BufferedImage;
      import javax.swing.JFrame;

      /**
       * Slow text rendering initialization.
       * 2-3 second delay on macOS Sierra
       * Core i7 (2.3 GHz)
       *
       */
      public class Sample {
      static final long initTime = System.nanoTime();
      static volatile long counter = 0;

      public static void main(String[] args) throws InterruptedException {

      Component comp = new // uncomment of the following lines
      NoText()
      // Text()
      // TextAfter()
      ;


      JFrame frame = new JFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(comp);
      frame.setBounds(100, 0, 500, 500);
      frame.setVisible(true);

      for(int i = 0; i <= 1000; i++){
      counter = i;
      comp.repaint();
      Thread.sleep(10);
      }
      }

      }



      /**
       * Windows without text rendering come up quickly.
       */
      class NoText extends Component{
      static long initTime = System.nanoTime();
      static long elapsedTime = -1;

      public void paint(Graphics g) {
      g.setColor(Color.GRAY);
      g.fillRect(10, 0, getWidth() - 20, 10);
      if(elapsedTime < 0){
      elapsedTime = System.nanoTime() - initTime;
      System.out.println((elapsedTime / 1_000_000) + " ms (init .. 1st render [no Text])");
      }
      }
      }

      /**
       * Rendering text takes a while the first time.
       */
      class Text extends Component{
      static long initTime = System.nanoTime();
      static long elapsedTime = -1;

      public void paint(Graphics g) {
      g.drawString("Hello World", 10, 30);
      if(elapsedTime == -1) elapsedTime = System.nanoTime() - initTime;
      g.drawString((elapsedTime / 1_000_000) + " ms (init .. 1st text render)", 10, 50);
      g.setColor(Color.GRAY);
      g.fillRect(10, 0, getWidth() - 20, 10);
      }
      }

      /**
       * Gets FontMetrics in a separate thread
       * Start rending non text graphics immediately
       * Once done the text rendering occurs little delay
       */
      class TextAfter extends Component{
      static long initTime = System.nanoTime();
      static boolean FONT_INIT = false; // set true once FontMetric is retrieved
      static long completeTime;
      static long elapsedTime0; // first rendering (no text)
      static long elapsedTime1; // FontLoaded
      static long elapsedTime2 = -1; // first text rendering after FontLoaded

      static{
      new Thread(() ->{
      new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY).createGraphics().getFontMetrics();
      java.awt.EventQueue.invokeLater(() ->{
      FONT_INIT = true;
      completeTime = System.nanoTime();
      elapsedTime1 = completeTime - initTime;
      });
      }).start();
      }

      public void paint(Graphics g) {
      long width = (getWidth()-20) * Sample.counter / 1000;
      g.setColor(Color.GRAY);
      g.fillRect(10, 0, (int) width, 10);
      if(FONT_INIT){
      g.setColor(Color.BLACK);
      g.drawString("Hello World", 10, 30);
      if(elapsedTime2 < 0) elapsedTime2 = System.nanoTime() - completeTime;
      g.drawString((elapsedTime0 / 1_000_000) +" ms (init .. 1st render)", 10, 50);
      g.drawString((elapsedTime1 / 1_000_000) +" ms (init .. FontMetrics)", 10, 70);
      g.drawString((elapsedTime2 / 1_000_000) +" ms (FontMetrics .. 1st text render)", 10, 90);
      }
      if(elapsedTime0 < 0) elapsedTime0 = System.nanoTime() - initTime;
      }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      Non-text can be rendered until font loading has been completed.


        1. 9-NoText.PNG
          9-NoText.PNG
          7 kB
        2. 9-Text.PNG
          9-Text.PNG
          3 kB
        3. 9-TextAfter.PNG
          9-TextAfter.PNG
          6 kB
        4. Sample.java
          3 kB

            prr Philip Race
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: