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: 5005831
Votes 4
Synopsis String constructors and method which take Charset rather than String as argument
Category java:classes_lang
Reported Against 1.4.2
Release Fixed mustang(b78)
State 10-Fix Delivered, request for enhancement
Priority: 3-Medium
Related Bugs 6393232 , 6400767 , 6402819
Submit Date 01-MAR-2004
Description


A DESCRIPTION OF THE REQUEST :
I have a large number of byte[] arrays and i know the charset name (UTF-8) of data in bytearrays. I am using jdk 1.4.2 . I was wondering what is the most   efficient way to create java.lang.string objects out of these byte arrays. The default string constructor of java accepts a charsetname and when i look into the sun java source code, it is doing comparisions etc.,. before it actually performs the conversion which i feel like inefficient

what is missing is a string constructor which takes a charset decoder as argument. Is there any way to get this into jdk 1.5 ?

I am looking at the most efficient solution because it is such a basic operation..

From what i can see, the performance improvements is 40%.

I am running the tests on a 2.2 Ghz  customer  P4 box and am using version of java as below.

C:\cadyformatter\src\java\lang>java -version
java version "1.4.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)

C:\cadyformatter\src\java\lang>java -Xbootclasspath:.;c:\jdk1.4\jre\lib\rt.jar StringTest
New api time : 10453
Old api time : 14282

C:\cadyformatter\src\java\lang>java -Xbootclasspath:.;c:\jdk1.4\jre\lib\rt.jar StringTest
New api time : 10515
Old api time : 14297

C:\cadyformatter\src\java\lang>java -Xbootclasspath:.;c:\jdk1.4\jre\lib\rt.jar StringTest
New api time : 10453
Old api time : 14281

The method i added to java.lang.String is

    public String(byte bytes[], int offset, int length, CharsetDecoder cd)
    {
        // note - the cd is not threadsafe, throw concurrent exception if it is used badly
        if (cd == null)
            throw new NullPointerException("null charset decoder");
        checkBounds(bytes, offset, length);
        cd.onMalformedInput(CodingErrorAction.REPLACE)
            .onUnmappableCharacter(CodingErrorAction.REPLACE);
        int en = (int)(cd.maxCharsPerByte() * length);
        char[] ca = new char[en];
        cd.reset();
        ByteBuffer bb = ByteBuffer.wrap(bytes, offset, length);
        CharBuffer cb = CharBuffer.wrap(ca);
        try {
            CoderResult cr = cd.decode(bb, cb, true);
            if (!cr.isUnderflow())
                cr.throwException();
            cr = cd.flush(cb);
            if (!cr.isUnderflow())
                cr.throwException();
        } catch (CharacterCodingException x) {
            // Substitution is always enabled,
            // so this shouldn't happen
            throw new Error(x);
        }
        value = ca;
        count = cb.position();
    }


JUSTIFICATION :
Converting bytes to strings is the most common operation in i/o bound apps and without this it is kind of inefficient.

Also, note that if I might be using custom UTF-8 Converter that i myself wrote rather than using the default, may be i can get much faster performance (I will writeup another test case for this and send it later).

Note that in a server side environment, this is the most frequently performed operation and hence it should be ultra efficient. I noted that many servers like Caucho resin server etc.,. which are opensource have gone extra lengths to make this as fast as possible getting around the current bottleneck in java.lang.String class.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Need to see a String ctor with charsetdecoder as argument - more better ultra optimizations for utf-8 strings which is a common case
ACTUAL -
Currently, a charset name string is passed as argument which internally does thread local lookup and a string comparision etc.,. before it actually does the converstion - the overhead seems to bemore than actual comparision for small strings.
(Incident Review ID: 240188) 
======================================================================
  xxxxx@xxxxx   2004-03-01
Work Around
N/A
Evaluation
We should add constructors and methods which parallel the ones which take a String charsetName:

  String(byte [] bytes, int offset, int length, Charset charset)
  String(byte [] bytes, Charset charset)
  public byte[] getBytes(Charset charset)
  xxxxx@xxxxx   2004-12-02 20:12:19 GMT
Contribution-Forum:https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?messageID=12050&forumID=1463
Posted Date : 2006-03-16 02:24:38.0
Comments
  
  Include a link with my name & email   

Submitted On 12-MAR-2004
evijaykumar
The other conversion of converting a string to array of 
bytes is also very inefficient. There should be a 
getByteBuffer() method which returns the byte buffer 
instead of byte[] array. 

Specially for utf-8 case, i notice that with the existing 
code, there is almost always a redundant and 
inefficient bytearray copy happening for getBytes() 
method if you pass a charset name and is really 
inefficient.



PLEASE NOTE: JDK6 is formerly known as Project Mustang