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

(bf) CharBuffer.put(String) is slow because of String.charAt() call for each char

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P3 P3
    • 13
    • None
    • core-libs
    • b10

      A DESCRIPTION OF THE REQUEST :
      CharBuffer.put(String) and CharBuffer.put(String,int,int) calls charAt() to retrieve the content of String as follows:
           public CharBuffer put(String src, int start, int end) {
               checkBounds(start, end - start, src.length());
               for (int i = start; i < end; i++)
                   this.put(src.charAt(i));
               return this;
           }

      This is very slow even for a String of moderate length (20-40 chars).
      Compared to char[] version, this makes serialization of String several times slower.

      As java.nio is JDK's internal package, this should use sun.misc.Unsafe to retrieve the internal char[] of String and just call put(char[]).

      JUSTIFICATION :
      For user programs, String is heavily protected and there is no recommended way to retrieve its char[] without making extra copy. So, CharBuffer.put(String) is the only bulk interface available to users, which is very slow because of this issue.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Process String serialization as a batch/bulk.
      ACTUAL -
      Calls charAt() and put() for every character.

      ---------- BEGIN SOURCE ----------
      import java.nio.CharBuffer;

      public class Test {
      public static void main(String[] args) {

      String str = new String ( " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 " );
      CharBuffer buf = CharBuffer.wrap(new char[100]);

      int REP = 1 << 22;
      {
      long st = System.currentTimeMillis();
      for (int i = 0; i < REP; ++i) {
      buf.position(0);
      buf.put(str);
      }
      long ed = System.currentTimeMillis();
      System.out.println ( " put(String): " + (ed - st) + " ms " );
      }

      char[] chars = str.toCharArray(); // extra copy
      {
      long st = System.currentTimeMillis();
      for (int i = 0; i < REP; ++i) {
      buf.position(0);
      buf.put(chars);
      }
      long ed = System.currentTimeMillis();
      System.out.println ( " put(char[]): " + (ed - st) + " ms " );
      }
      }
      }

      == Result
      put(String):221ms
      put(char[]):57ms

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

      CUSTOMER SUBMITTED WORKAROUND :
      Either use sun.misc.Unsafe in user code (not recommended at all) or copy char[] from String using toCharArray()/copyValueOf() (extra overhead/footprint).

            bpb Brian Burkhalter
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: