Is it better to reuse a StringBuilder in a loop?

前端 未结 14 2101
名媛妹妹
名媛妹妹 2020-12-04 06:46

I\'ve a performance related question regarding use of StringBuilder. In a very long loop I\'m manipulating a StringBuilder and passing it to another method like

14条回答
  •  被撕碎了的回忆
    2020-12-04 07:07

    The reason why doing a 'setLength' or 'delete' improves the performance is mostly the code 'learning' the right size of the buffer, and less to do the memory allocation. Generally, I recommend letting the compiler do the string optimizations. However, if the performance is critical, I'll often pre-calculate the expected size of the buffer. The default StringBuilder size is 16 characters. If you grow beyond that, then it has to resize. Resizing is where the performance is getting lost. Here's another mini-benchmark which illustrates this:

    private void clear() throws Exception {
        long time = System.currentTimeMillis();
        int maxLength = 0;
        StringBuilder sb = new StringBuilder();
    
        for( int i = 0; i < 10000000; i++ ) {
            // Resetting the string is faster than creating a new object.
            // Since this is a critical loop, every instruction counts.
            //
            sb.setLength( 0 );
            sb.append( "someString" );
            sb.append( "someString2" ).append( i );
            sb.append( "someStrin4g" ).append( i );
            sb.append( "someStr5ing" ).append( i );
            sb.append( "someSt7ring" ).append( i );
            maxLength = Math.max(maxLength, sb.toString().length());
        }
    
        System.out.println(maxLength);
        System.out.println("Clear buffer: " + (System.currentTimeMillis()-time) );
    }
    
    private void preAllocate() throws Exception {
        long time = System.currentTimeMillis();
        int maxLength = 0;
    
        for( int i = 0; i < 10000000; i++ ) {
            StringBuilder sb = new StringBuilder(82);
            sb.append( "someString" );
            sb.append( "someString2" ).append( i );
            sb.append( "someStrin4g" ).append( i );
            sb.append( "someStr5ing" ).append( i );
            sb.append( "someSt7ring" ).append( i );
            maxLength = Math.max(maxLength, sb.toString().length());
        }
    
        System.out.println(maxLength);
        System.out.println("Pre allocate: " + (System.currentTimeMillis()-time) );
    }
    
    public void testBoth() throws Exception {
        for(int i = 0; i < 5; i++) {
            clear();
            preAllocate();
        }
    }
    

    The results show reusing the object is about 10% faster than creating a buffer of the expected size.

提交回复
热议问题