4 Replies Latest reply on Mar 31, 2014 2:43 PM by rp0428

    oom playing with StringBuilder and String

    didisoft

      hi list

       

      i want check the diff between partial string concatination using stringbuffer (pmd create a hint around using the + inside stringbufffer.append).

       

      now i write follow sample code:

       

      public class StringBuffererf

      {

          public static void main(String[] args)

          {

             

              long nrLoops =100000000;

             

              StringBuffer sb = new StringBuffer();

             

              long start = System.currentTimeMillis();

             

              for (int i=0; i<=nrLoops; i++)

              {

                  if (i/1000 == 0)

                  {

                      sb = new StringBuffer();

                  }

                  sb.append("asd1" + "asd2" + "asd3" + "asd4" + "asd5" + "asd1" + "asd2" + "asd3" + "asd4" + "asd5");

              }

             

              System.out.println("duration: " + (System.currentTimeMillis()-start));

             

              start = System.currentTimeMillis();

             

             

              for (int i=0; i<=nrLoops; i++)

              {

                  if (i/1000 == 0)

                  {

                      sb = new StringBuffer();

                  }

                  sb.append("asd1");

                  sb.append("asd2");

                  sb.append("asd3");

                  sb.append("asd4");

                  sb.append("asd5");

                  sb.append("asd1");

                  sb.append("asd2");

                  sb.append("asd3");

                  sb.append("asd4");

                  sb.append("asd5");

              }

             

              System.out.println("duration: " + (System.currentTimeMillis()-start));

          }

      }

       

      one interesting around this code is: partial + operations inside a stringbuffer ist faster then use everytime an append.

       

      but if i increase the number of loops i get an oom.

       

      imho i don't expect this, because with

       

      if (i/1000 == 0)

      {

           sb = new StringBuffer();

      }

       

      i though, that this release the object and free also the memory.

       

      what i wrong around this and what i the cause for the oom.

       

      any hint and or tip is welcome

       

      best regards

      dietmar

        • 1. Re: oom playing with StringBuilder and String
          jschellSomeoneStoleMyAlias

          The expression "i/1000" doesn't do what you think it does.

           

          You are not testing concatenation the way you have written it because the compiler, not the VM is doing the concatenation.

           

          Presumably you understand the difference between StringBuilder and StringBuffer.

          • 2. Re: oom playing with StringBuilder and String
            rp0428

            but if i increase the number of loops i get an oom.

            imho i don't expect this, because with

             

            if (i/1000 == 0)

            {

                 sb = new StringBuffer();

            }

             

            i though, that this release the object and free also the memory.

            That DOES release the object and free the memory once the garbage collector runs.

             

            But that isn't your problem. Answer these questions

             

            1. How many times will that 'new StringBuffer' line will be executed?

            2. what is 1/1000?

            3. what is 999/1000?

            4. what is 1000/1000?

            5. what is 1001/1000?

             

            That line will be executed 999 times (for i from 1 to 999). After that i/1000 will NEVER be zero again.

             

            Which means that this line:

            sb.append("asd1" + "asd2" + "asd3" + "asd4" + "asd5" + "asd1" + "asd2" + "asd3" + "asd4" + "asd5");

            will execute for all but 1000 of those 100 million iterations ON THE SAME STRINGBUFFER!

             

            You are asking Java to append that set of 40 characters almost 100 million times. That would be about 4 BILLION characters.

             

            Do you have your heap set large enough for that?

             

            Perhaps you meant to use the modulo operator (i.e. %) instead of division?

            1 person found this helpful
            • 3. Re: oom playing with StringBuilder and String
              didisoft

              thanks both for the answers.

               

              you are right --> the / was the mistake!

              also you are right StringBuffer is the wrong class for this!

               

              on other side: i did some changes in the code and use a pure string loop --> this is really slow!

              StringBuilder is fast.

              But if i use a mix from string concatinations with string literals and StringBuilder i'll get the fastest code.

               

              generally i think i understand parts from the string things inside jvm but i don't expect this kind of optimizations, when all strings are knows literales or is this a compiler optimizations?

               

              if someone have a link around this pls let me know.

               

              thanks

              • 4. Re: oom playing with StringBuilder and String
                rp0428
                also you are right StringBuffer is the wrong class for this!

                No one said that StringBuffer is 'the wrong class'. jschell did say this:

                Presumably you understand the difference between StringBuilder and StringBuffer.

                That is likely because your thread subject said 'playing with StringBuilder and String' but your sample code didn't use either one of those; it used StringBuffer instead.

                 

                Instances of the String class are NOT mutable while instances of StringBuilder or StringBuffer are.

                 

                Which of the latter two classes to use depends on your use case. StringBuilder is NOT thread-safe and does NOT guarantee synchronization so is targeted more for single-threaded use.

                 

                See the Java APIs

                http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html

                A mutable sequence of characters. This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.

                http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuffer.html

                A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified. At any point in time it contains some particular sequence of characters, but the length and content of the sequence can be changed through certain method calls. 

                 

                String buffers are safe for use by multiple threads. The methods are synchronized where necessary so that all the operations on any particular instance behave as if they occur in some serial order that is consistent with the order of the method calls made by each of the individual threads involved.