"Kevin O'Neill"                                                  
                                             
                      <kevin@rocketred.        To:       FOP Developers 
<[EMAIL PROTECTED]>                                    
                      com.au>                  cc:       (bcc: Thomas 
Seremet/GCR-NAmerica/GRN)                                     
                                               Subject:  Re: A performance patch for 
PDFInfo class                                  
                      11/13/2002 05:41                                                 
                                             
                      AM                                                               
                                             
                      Please respond to                                                
                                             
                      fop-dev                                                          
                                             
                                                                                       
                                             
                                                                                       
                                             









><snip/>
>
>> Some more insight or confusion. The byte code maybe similar in the sense
>> that String uses "".concat() and
>> StringBuffer uses new StringBuffer().append to do their individual
>> concatenations but the way they are
>> treated by the JVM is not the same. Of course not all JVM's are created
>> equal but Strings are stored as constants thus you see the ldc opcode
when
>> creating Strings. Even though a String holds on to an internal
>> character array as does a StringBuffer, a String creates a new String
when
>> it is concatentating another String to itself NOT modifing its internal
>> character array. On the other hand a StringBuffer actually modifies its
>> internal character array to represent the new String though this is
>> accomplished by increasing the array size by creating a new char array.
>> This is only part of the story since there is a difference between
Strings
>> stored in the so-called constants pool and new Strings created during
>> runtime which do not go into the constants-pool automatically. Very good
>> info concerning this on the web.
>
>Okay firstly, please look at the pcode generated earlier in this thread.
>It was generated by the moder compiler on jdk 1.4.0 the string addition
>is indeed concatinated using StringBuffer.append()
>
>    public String testStringBufferChained()
>    {
>            return (new StringBuffer().append("this ")
>                .append(makeString("is "))
>                .append("a ")
>                .append(makeString("test"))).toString();
>    }
>
>    public String testStringAdd()
>    {
>            return
>                "this "
>                + makeString("is ")
>                + "a "
>                + makeString("test");
>    }
>
>becomes ...
>
>Method java.lang.String testStringBufferChained()
>   0 new #2 <Class java.lang.StringBuffer>
>   3 dup
>   4 invokespecial #3 <Method java.lang.StringBuffer()>
>   7 ldc #4 <String "this ">
>   9 invokevirtual #5 <Method java.lang.StringBuffer
>append(java.lang.String)>
>  12 aload_0
>  13 ldc #6 <String "is ">
>  15 invokespecial #7 <Method java.lang.String
>makeString(java.lang.String)>
>  18 invokevirtual #5 <Method java.lang.StringBuffer
>append(java.lang.String)>
>  21 ldc #8 <String "a ">
>  23 invokevirtual #5 <Method java.lang.StringBuffer
>append(java.lang.String)>
>  26 aload_0
>  27 ldc #9 <String "test">
>  29 invokespecial #7 <Method java.lang.String
>makeString(java.lang.String)>
>  32 invokevirtual #5 <Method java.lang.StringBuffer
>append(java.lang.String)>
>  35 invokevirtual #10 <Method java.lang.String toString()>
>  38 areturn
>
>Method java.lang.String testStringAdd()
>   0 new #2 <Class java.lang.StringBuffer>
>   3 dup
>   4 invokespecial #3 <Method java.lang.StringBuffer()>
>   7 ldc #4 <String "this ">
>   9 invokevirtual #5 <Method java.lang.StringBuffer
>append(java.lang.String)>
>  12 aload_0
>  13 ldc #6 <String "is ">
>  15 invokespecial #7 <Method java.lang.String
>makeString(java.lang.String)>
>  18 invokevirtual #5 <Method java.lang.StringBuffer
>append(java.lang.String)>
>  21 ldc #8 <String "a ">
>  23 invokevirtual #5 <Method java.lang.StringBuffer
>append(java.lang.String)>
>  26 aload_0
>  27 ldc #9 <String "test">
>  29 invokespecial #7 <Method java.lang.String
>makeString(java.lang.String)>
>  32 invokevirtual #5 <Method java.lang.StringBuffer
>append(java.lang.String)>
>  35 invokevirtual #10 <Method java.lang.String toString()>
>  38 areturn
>
>
>So once again I say these are these are identical, the underlying VM has
>no idea of any difference. I would though contend that the String
>addition is easier to read.

I know I also came in late into this thread. I would like to say I am very
excited about the possibilities of FOP in the future and the already
realized gains FOP gives. My overall grasp of FOP at this moment is still
limited but I have been delving into the code and using it for a current
project for the past 2 months. In no way am I trying to be insulting to
anyone. I realize everyone here is very well versed in various areas of
programming. Performance has always been an interest to me in general so I
enjoy these types of topics. I don't mind being proven wrong.

Yes. You are correct on your assumptions based on your code.

Maybe I should have been more clear and read the initial beginning to this
thread but I would like to clear two points up, my apologies.

I was trying to refer to two seperate issues that were being discussed,
more so to what happens during runtime then compile time.

The first point was what the String and StringBuffer java code looks in the
pcode. String does do concantenation with the concat method and
StringBuffer with append?.

It does do that except under certain conditions.

So, what are the conditions under the + operator?

-If there is a chain of anonymous strings being initialized to a variable a
LOAD happens.
-If there is 1 reference to a String at the head or end of a chain of
anonymous Strings a String.concat happens
-If there are only 2 references to a String(s) being "concantenated using +
operator" a String.concat happens
-If the chain contains 2 or more anonymous strings seperated by at least 1
reference to a String StringBuffer.append happens
-If the chain contains 3 or more references to a String(s)
StringBuffer.append happens
-If the chain contains at least 2 references to a String(s) and at least 1
anonymous String StringBuffer.append happens

What are the conditions for += operator?

-They are the same as above except for the additional concantenation that
happens implicitly to the variable adding to itself.

So to the statement that StringBuffer.append happens in "String addition"
is only partly true given String.concat happens in a subset of the cases.

Code below  JDK 1.4.0_01-b03:

 public Test()
  {

      String a = "foo";
      a += "bar";

      String b = "so" + "far" + "so" + "good";

      String c = "boo" + "far" + a;

      String d = b + c;

      String e = a + b + c;

      String f = makeString("goo") + makeString("bar");

      String g = "boo" + a + "far";

      d += e + f;

      d += "foo"+"bar"+"foo";

      d += "boo" + "bar" + e;

      d += "boo" + e + "bar";

      String h = b + b;

      String x = b + c + "end";

  }


public Test()
    {
    //    0    0:aload_0
    //    1    1:invokespecial   #1   <Method void Object()>
        String a = "foo";
    //    2    4:ldc1            #3   <String "foo">
    //    3    6:astore_1
        a = String.valueOf(String.valueOf(a)).concat("bar");
    //    4    7:aload_1
    //    5    8:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //    6   11:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //    7   14:ldc1            #5   <String "bar">
    //    8   16:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //    9   19:astore_1
        String b = "sofarsogood";
    //   10   20:ldc1            #7   <String "sofarsogood">
    //   11   22:astore_2
        String c = "boofar".concat(String.valueOf(String.valueOf(a)));
    //   12   23:ldc1            #8   <String "boofar">
    //   13   25:aload_1
    //   14   26:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   15   29:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   16   32:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //   17   35:astore_3
        String d = String.valueOf(b) + String.valueOf(c);
    //   18   36:aload_2
    //   19   37:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   20   40:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   21   43:aload_3
    //   22   44:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   23   47:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   24   50:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //   25   53:astore          4
        String e = String.valueOf(String.valueOf((new
StringBuffer(String.valueOf(String.valueOf(a)))).append(b).append(c)));
    //   26   55:new             #9   <Class java.lang.StringBuffer>
    //   27   58:dup
    //   28   59:aload_1
    //   29   60:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   30   63:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   31   66:invokespecial   #10  <Method void
StringBuffer(java.lang.String)>
    //   32   69:aload_2
    //   33   70:invokevirtual   #11  <Method java.lang.StringBuffer
java.lang.StringBuffer.append(java.lang.String)>
    //   34   73:aload_3
    //   35   74:invokevirtual   #11  <Method java.lang.StringBuffer
java.lang.StringBuffer.append(java.lang.String)>
    //   36   77:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   37   80:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   38   83:astore          5
        String f = String.valueOf(makeString("goo")) +
String.valueOf(makeString("bar"));
    //   39   85:aload_0
    //   40   86:ldc1            #12  <String "goo">
    //   41   88:invokespecial   #13  <Method java.lang.String
tester.Test.makeString(java.lang.String)>
    //   42   91:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   43   94:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   44   97:aload_0
    //   45   98:ldc1            #5   <String "bar">
    //   46  100:invokespecial   #13  <Method java.lang.String
tester.Test.makeString(java.lang.String)>
    //   47  103:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   48  106:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   49  109:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //   50  112:astore          6
        String g = String.valueOf(String.valueOf((new StringBuffer("boo
")).append(a).append("far")));
    //   51  114:new             #9   <Class java.lang.StringBuffer>
    //   52  117:dup
    //   53  118:ldc1            #14  <String "boo">
    //   54  120:invokespecial   #10  <Method void
StringBuffer(java.lang.String)>
    //   55  123:aload_1
    //   56  124:invokevirtual   #11  <Method java.lang.StringBuffer
java.lang.StringBuffer.append(java.lang.String)>
    //   57  127:ldc1            #15  <String "far">
    //   58  129:invokevirtual   #11  <Method java.lang.StringBuffer
java.lang.StringBuffer.append(java.lang.String)>
    //   59  132:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   60  135:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   61  138:astore          7
        d = String.valueOf(d) + String.valueOf(String.valueOf(e) +
String.valueOf(f));
    //   62  140:aload           4
    //   63  142:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   64  145:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   65  148:aload           5
    //   66  150:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   67  153:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   68  156:aload           6
    //   69  158:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   70  161:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   71  164:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //   72  167:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   73  170:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   74  173:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //   75  176:astore          4
        d = String.valueOf(String.valueOf(d)).concat("foobarfoo");
    //   76  178:aload           4
    //   77  180:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   78  183:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   79  186:ldc1            #16  <String "foobarfoo">
    //   80  188:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //   81  191:astore          4
        d = String.valueOf(d) + String.valueOf("boobar
".concat(String.valueOf(String.valueOf(e))));
    //   82  193:aload           4
    //   83  195:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   84  198:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   85  201:ldc1            #17  <String "boobar">
    //   86  203:aload           5
    //   87  205:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   88  208:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   89  211:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //   90  214:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   91  217:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   92  220:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //   93  223:astore          4
        d = String.valueOf(d) +
String.valueOf(String.valueOf(String.valueOf((new StringBuffer("boo
")).append(e).append("bar"))));
    //   94  225:aload           4
    //   95  227:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   96  230:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //   97  233:new             #9   <Class java.lang.StringBuffer>
    //   98  236:dup
    //   99  237:ldc1            #14  <String "boo">
    //  100  239:invokespecial   #10  <Method void
StringBuffer(java.lang.String)>
    //  101  242:aload           5
    //  102  244:invokevirtual   #11  <Method java.lang.StringBuffer
java.lang.StringBuffer.append(java.lang.String)>
    //  103  247:ldc1            #5   <String "bar">
    //  104  249:invokevirtual   #11  <Method java.lang.StringBuffer
java.lang.StringBuffer.append(java.lang.String)>
    //  105  252:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  106  255:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  107  258:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  108  261:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  109  264:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //  110  267:astore          4
        String h = String.valueOf(b) + String.valueOf(b);
    //  111  269:aload_2
    //  112  270:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  113  273:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  114  276:aload_2
    //  115  277:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  116  280:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  117  283:invokevirtual   #6   <Method java.lang.String
java.lang.String.concat(java.lang.String)>
    //  118  286:astore          8
        String x = String.valueOf(String.valueOf((new
StringBuffer(String.valueOf(String.valueOf(b)))).append(c).append("end")));
    //  119  288:new             #9   <Class java.lang.StringBuffer>
    //  120  291:dup
    //  121  292:aload_2
    //  122  293:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  123  296:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  124  299:invokespecial   #10  <Method void
StringBuffer(java.lang.String)>
    //  125  302:aload_3
    //  126  303:invokevirtual   #11  <Method java.lang.StringBuffer
java.lang.StringBuffer.append(java.lang.String)>
    //  127  306:ldc1            #18  <String "end">
    //  128  308:invokevirtual   #11  <Method java.lang.StringBuffer
java.lang.StringBuffer.append(java.lang.String)>
    //  129  311:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  130  314:invokestatic    #4   <Method java.lang.String
java.lang.String.valueOf(java.lang.Object)>
    //  131  317:astore          9
    //  132  319:return
    }



The point that is more interesting is what happens during runtime and
that's what I was trying to emphasize, poorly.

The question is how many String objects are being handled by the JVM in
memory, how often garbage collection happens, and at what cost? I have not
timed your examples but I believe what you stated. I have run similar tests
but from a different angle. The only difference between tests was that they
were controlled within a loop. The times were different. The reason I did
this is to see how much memory and time is spent within the scope of each
method.

The testStringAppendloop was exponentially faster with testStringAddloop
coming in second and third for testStringIncrementloop. The times of course
will differ on different platforms and cpu's but I list them anyway.

This is my sample code derived from your examples; byte-code following.
1.4.0_01-b03

times with 3000 iterations compaq 512 mb 866ghz intel cpu:
16 ms testStringAppendloop
2000 ms testStringAddloop
5531 ms testStringIncrementloop

public String testStringIncrementloop(int loop)
    {
        String temp = "";

        for (int i=0;i<loop;i++)
        {
          temp += makeString("this is ");
          temp += "a ";
          temp += makeString("concat test");
        }

        return temp;

    }

    public String testStringAddloop(int loop)
    {
        String temp = "";

        for (int i=0;i<loop;i++)
        {
          temp = temp + makeString("this is ") + "a " + makeString("concat
test");
        }

        return temp;
    }

    public String testStringAppendloop(int loop)
    {
        StringBuffer temp = new StringBuffer("");

        for (int i=0;i<loop;i++)
        {
          temp.append(makeString("this is ")).append("a
").append(makeString("concat test"));
        }

        return temp.toString();
    }

-Tom



















---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, email: [EMAIL PROTECTED]

Reply via email to