StringBuffer failure



  • Working on a class project, we were asked by the prof to use StringBuffers (Java) to speed up execution time. 

    This student made a nice attempt, but the concept was slightly out of reach. 

     

    public String toString(){
            StringBuffer output = new StringBuffer();
                   
            output.append("Time: " + getTime()+ "\t");
            output.append("Wind Dir: " + getWindDirection()+ "\t");
            output.append("Wind Speed mph: " + getWindSpeed()+ "\t");
            output.append("Wind Gust mph: " + getWindGust()+ "\t");
            output.append("Humidity %: " + getRelativeHumidity()+ "\t");
            output.append("Temp In F: " + getInsideTemperature()+ "\t");
            output.append("Temp F: " + getOutsideTemperature()+ "\t");
            output.append("Raw Barom mb: " + getBarometricPressure()+ "\t");
            output.append("Tot Rain in: " + getAnnualRainfall()+ "\t");
            output.append("ET in: " + getEvapotranspiration()+ "\t");
            output.append("UV: " + getUltravioletRadiation()+ "\t");
            output.append("Solar W/sqm: " + getSolarRadiation()+ "\t");
            output.append("Wind Chill F: " + getWindChill()+ "\t");
            output.append("Heat Ix In F: " + getInsideHeatIndex()+ "\t");
            output.append("Heat Index: " + getOutsideHeatIndex()+ "\t");
            output.append("Dew Point: " + getDewPoint()+ "\t");
            output.append("Barom SL mb: " + getBarometricPressureSL()+ "\t");
            output.append("Press Alt ft: " + getPressureAltitude()+ "\t");
            output.append("Cloud Base ft: " + getCloudBase()+ "\t");
            output.append("Dens Alt ft: " + getDensityAltitude()+ "\t");
            output.append("Virt Temp F: " + getVirtualTemperature()+ "\t");
            output.append("Vapor Press mb: " + getPressure()+ "\t");
            output.append("DailyRain in: " + getDailyRainfall()+ "\t");
            output.append("HourRain in: " + getHourlyRainfall() + "\t");
            output.append("24HrRain in: " + getTwentyFourHourRainfall()+ "\t");
            output.append("RainRate in/hr: " + getRainfallRate()+ "\t");
            output.append("Wind Run miles: " + getWindRun()+ "\t");
            output.append("Deg Heat F: " + getHeatingDegrees()+ "\t");
            output.append("Deg Cool F: " + getCoolingDegrees()+ "\t");           
            output.append("Moon Phase: " + getMoonPhase()+ "\t");
            output.append("MonthRain in: " + getMonthlyRainfall()+ "\t");
            output.append("DegHeat Mo F: " + getMonthlyHeatingDegrees()+ "\t");
            output.append("DegCool Mo F: " + getMonthlyCoolingDegrees()+ "\t");   
            output.append("WindRun Mo Miles: " + getMonthlyWindRun()+ "\t");
            output.append("DegHeat Yr F: " + getYearlyHeatingDegrees()+ "\t");        
            output.append("DegCool Yr F: " + getYearlyCoolingDegrees()+ "\t");   
            output.append("WindRun Yr Miles: " + getYearlyWindRun()+ "\n");  
           
            return output.toString();
        }



  • I think the best way to convey the aproppiate response to this solution is to revive an old classic of this forum...




  • @brillohead16 said:

    Working on a class project, we were asked by the prof to use StringBuffers (Java) to speed up execution time. 

    Which, ironically enough, was obsoleted by java compilers a couple of years ago (and about ten years too late, in my opinion - it's a really simple optimisation). If you ran javap over the bytecode generated for that function, you'd find that the compiler emitted nothing but stringbuffer appends...



  • @asuffield said:

    @brillohead16 said:

    Working on a class project, we were asked by the prof to use StringBuffers (Java) to speed up execution time. 

    Which, ironically enough, was obsoleted by java compilers a couple of years ago (and about ten years too late, in my opinion - it's a really simple optimisation). If you ran javap over the bytecode generated for that function, you'd find that the compiler emitted nothing but stringbuffer appends...

     

     

    To the best of my knoledge the lines would be optimized by the compiler to something like this....

    myBuffer.append(new mybuffer("a").append("b").append("c"));

    am i wrong on this assumption? 



  • For some reason I'm unable to edit my post. Posting my code snippet again with a spelling correction for clearity.

    myBuffer.append(new StringBuffer("a").append("b").append("c"));



  •  That's what I'm wondering.  Is the Java compiler smart enough to throw all the concatenations together as appending to one string buffer, or will it interpret each concatenation as its own string buffer.   The person who did this may have in fact found a way to use string buffers to make the execution slower than using straight concatenation.



  • @brillohead16 said:

    To the best of my knoledge the lines would be optimized by the compiler to something like this....

    myBuffer.append(new mybuffer("a").append("b").append("c"));

    am i wrong on this assumption? 

    There's no reason why the compiler can't optimise out the unnecessary extra copy, but I haven't checked to see which (if any) of them do. 



  • Indeed using '+' in string does internally use a StringBuffer up to, including, java 1.4 and as such, for above code, using explicitly StringBuffer, is useless on such platform. Worse, starting in java 5, StringBuffer for building strings internally was replaced by StringBuilder, which is not synchronized and as such far more performant on multi-cpu platforms. (StringBuffer is synchronized, and if you are using more that one cpu, the synchronization is a relatively slow process that include some memory/bus locking procedures to acquire exclusively the sync flag for only a couple of instructions, which is quite ennoying when you try to optimize :) )



  •  @tchize said:

    Indeed using '+' in string does internally use a StringBuffer up to, including, java 1.4

    I guess what im confused about now is how it uses it. My confusion is whether or not the compiler is actually smart enough to know that it can optimize when a combination of buffers and string concats are used.  in this specific case, does this use only one instance of stringBuffer?

    Also In java 1.6, is string builder now used implicitly? would this be replaced with a strange combination of buffers and builders?



  • output.append("Dens Alt ft: " + getDensityAltitude()+ "\t");
    output.append("Virt Temp F: " + getVirtualTemperature()+ "\t");
    output.append("Vapor Press mb: " + relievePressure()+ "\t");
    output.append("DailyRain in: " + getDailyRainfall()+ "\t");
    output.append("HourRain in: " + getHourlyRainfall() + "\t");

    Fixed that for you. 



  • Sun's Java 1.6 compiler seems to create multiple StringBuilders.  With this program:

    public static void main(String[] args)
    {
    ..StringBuilder sb = new StringBuilder();
    ..sb.append("ONE" + new String("TWO"));
    }

    I get this bytecode:

    public static void main(java.lang.String[]);
      Code:
       0:    new    #2; //class java/lang/StringBuilder
       3:    dup
       4:    invokespecial    #3; //Method java/lang/StringBuilder."<init>":()V
       7:    astore_1
       8:    aload_1
       9:    new    #2; //class java/lang/StringBuilder
       12:    dup
       13:    invokespecial    #3; //Method java/lang/StringBuilder."<init>":()V
       16:    ldc    #4; //String ONE
       18:    invokevirtual    #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       21:    new    #6; //class java/lang/String
       24:    dup
       25:    ldc    #7; //String TWO
       27:    invokespecial    #8; //Method java/lang/String."<init>":(Ljava/lang/String;)V
       30:    invokevirtual    #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       33:    invokevirtual    #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
       36:    invokevirtual    #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       39:    pop
       40:    return
    }

     I'm no Java byte code master but I'm guessing that says 2 StringBuilders are created?



  • @brillohead16 said:

     @tchize said:

    Indeed using '+' in string does internally use a StringBuffer up to, including, java 1.4

    I guess what im confused about now is how it uses it. My confusion is whether or not the compiler is actually smart enough to know that it can optimize when a combination of buffers and string concats are used.  in this specific case, does this use only one instance of stringBuffer?

    Also In java 1.6, is string builder now used implicitly? would this be replaced with a strange combination of buffers and builders?

     

    Combinaison of stringbuilder and stringbuffer, stringbuilder for the concat, stringbuffer for part epxlicitly asked by developper.

    Using explicitly stringbuilder/stringbuffer is ony usefull in java where you know you are making lots of concats that the compiler won't optimize for you. Like spreading the concat in different methods or using loops with conditionnal logic in it 



  • @tchize said:

    Using explicitly stringbuilder/stringbuffer is ony usefull in java where you know you are making lots of concats that the compiler won't optimize for you. Like spreading the concat in different methods or using loops with conditionnal logic in it 

    And if you're doing all that and the code is slow enough to need optimising, you should be giving serious thought to whether Java is the correct language to be writing this code in.


Log in to reply