Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4930801
Votes 1
Synopsis Excessive CPU time when Unicode character list displayed under Japanese environm
Category java:classes_2d
Reported Against 1.4.2
Release Fixed
State 11-Closed, duplicate of 4641861, bug
Priority: 4-Low
Related Bugs 4641861
Submit Date 01-OCT-2003
Description



When Unicode character list is displayed using a sample Java program under Japanese environment, too much CPU time is used.

The CharacterList program accepts two option parameter. The first one is the interval of screen updates in millseconds and the second one is number of Unicode characters to be displayed in order. 

If the program was invoked with:
java CharacterList 500 1000 
it will display only first 1000 characters of CJK Unified Ideographs and the CPU usage is very low. 

If the program was invoked with:
java CharacterList 500 2000 
it will display first 2000 characters and CPU usage is almost 100%.  

/*
 * CharacterList.java
 */

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class CharacterList extends JPanel {

    public CharacterList() {        
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        font = new Font("Monospaced", Font.PLAIN, 16);
        codePoint = codePointLow;
        timer = new Timer(interval, 
            new ActionListener() {
                public void actionPerformed(ActionEvent e){
                    repaint();
                }
            });
        timer.start();
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        this.g = g;

        int panelWidth = getWidth();
        int panelHeight = getHeight();

        g.setFont(font);
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, panelWidth, panelHeight);
        g.setColor(Color.BLACK);

        if (stringLength == 0) {
            FontMetrics fm = g.getFontMetrics();
            width = fm.charWidth(FULL_WIDTH_ZERO);
            height = fm.getHeight();
        }
        
        stringLength = panelWidth / width;
        
        for (int y = height; y < panelHeight; y += height)
            g.drawString(getString(), 0, y);
    }
    
    public String getString() {
        char[] ca = new char[stringLength];
        
        for (int i =0; i < stringLength; ++i) {
            ca[i] = (char)codePoint++;
            if (codePoint > codePointHigh)
                codePoint = codePointLow;
        }
        
        return new String(ca);
    }
    
    public static void main(String[] args) {
        interval = DEFAULT_INTERVAL;
        try {
            interval = Integer.parseInt(args[0]);
            if (args.length > 1) {
                numberOfCharacters = Integer.parseInt(args[1]);
                codePointHigh = codePointLow + numberOfCharacters;
            }
        } catch (Exception e) {
        }
        
        System.out.println("redraw interval (msec) = " + interval);
        if (numberOfCharacters > 0)
            System.out.println("number of characters to be displayed in the list = " 
                + numberOfCharacters);
            
        JFrame frame = new JFrame(TITLE);
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        
        frame.setContentPane(new CharacterList());
        frame.pack();
        frame.setResizable(false);
        frame.setVisible(true);
    }
    
    private Font font;
    private int codePoint;
    private int width, height, stringLength;
    
    private Timer timer;
    private Graphics g;

    private static final String TITLE = "CharacterList";
    private static final int WIDTH = 400;
    private static final int HEIGHT = 400;
    
    private static final char FULL_WIDTH_ZERO = '\uff10';

    private static final int CODE_POINT_LOW = 0x4e00;
    private static final int CODE_POINT_HIGH = 0x9fff;

    private static final int DEFAULT_INTERVAL = 500;

    private static int interval;
    private static int numberOfCharacters;
    private static int codePointLow = CODE_POINT_LOW;
    private static int codePointHigh = CODE_POINT_HIGH;
}

======================================================================
Work Around
N/A
Evaluation
I was able to reproduce this on a 1.7 P4 under XP
The larger number of glyphs (2000) for the JA font is I think exceeding
the glyph cache in 1.4.2, so the expensive rasterisation of these glyphs
is happening for every display, which pretty much throttles the CPU.

The good news is that 1.5 fixed this and the same test case ticks along
at about 1% CPU usage in 1.5. In fact I can increase the number of glyphs
and reduce the time interval and the window really flies in 1.5

This kind of (usability) improvement was one of the goals of the 1.5 fix.

I am closing this as a duplicate of the work reponsible for this fix:
4641861: Improve performance of Java 2D font implementation

  xxxxx@xxxxx   2003-10-16
============================
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang