[stringtemplate-interest] Performance improvement in AutoIndentWriter

Sam Harwell sharwell at pixelminegames.com
Tue Mar 17 11:24:18 PDT 2009


In repeated profiling, I found that AutoIndentWriter.Write(string)
consumed just over 10% of the processing time. It was the most expensive
terminal function inside StringTemplate. I was able to cut that better
than in half by using faster string operations, and only when necessary.
Here is my code before and after the change.

 

Before:

 

public virtual int Write( string str )

{

    int n = 0;

    int strLength = str.Length;

    int newlineLength = _newline.Length;

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

    {

        char c = str[i];

        // found \n or \r\n newline?

        if ( c == '\r' || c == '\n' )

        {

            _atStartOfLine = true;

            n += newlineLength; // wrote n more char

            _writer.Write( _newline );

            _charPosition = 0; 

            // skip an extra char upon \r\n

            if ( ( c == '\r' && ( i + 1 ) < strLength && str[i+1] ==
'\n' ) )

            {

                i++; // loop iteration i++ takes care of skipping 2nd
char

            }

            continue;

        }

        // normal character

        // check to see if we are at the start of a line; need indent if
so

        if ( _atStartOfLine )

        {

            n += Indent();

            _atStartOfLine = false;

        }

        n++;

        _writer.Write( c );

        _charPosition++;

    }

    return n;

}

 

 

After:

 

public virtual int Write( string str )

{

    if ( string.IsNullOrEmpty( str ) )

    {

        return 0;

    }

    else if ( str.Contains( '\n' ) || str.Contains( '\r' ) )

    {

        str = str.Replace( "\r\n", "\n" );

        str = str.Replace( '\r', '\n' );

        if ( _indents.Count > 1 )

        {

            string[] lines = str.Split( '\n' );

            string indent = null;

            for ( int i = 0; i < lines.Length; i++ )

            {

                if ( ( i > 0 || _charPosition == 0 ) && lines[i].Length
> 0 )

                {

                    if ( indent == null )

                    {

                        indent = string.Join( string.Empty,
_indents.ToArray() );

                        if ( indent.Length == 0 )

                            break;

                    }

 

                    lines[i] = indent + lines[i];

                }

            }

 

            if ( lines.Length == 1 )

            {

                str = lines[0];

                _charPosition += str.Length;

            }

            else

            {

                str = string.Join( _newline, lines );

                _charPosition = lines[lines.Length - 1].Length;

            }

        }

        else

        {

            if ( _newline != "\n" )

                str = str.Replace( "\n", _newline );

            _charPosition = str.Length - str.LastIndexOf(
_newline[_newline.Length - 1] ) - 1;

        }

    }

    else

    {

        if ( _charPosition == 0 && _indents.Count > 1 )

        {

            string indent = string.Join( string.Empty,
_indents.ToArray() );

            str = indent + str;

        }

 

        _charPosition += str.Length;

    }

 

    Writer.Write( str );

 

    _atStartOfLine = ( _charPosition == 0 );

    return str.Length;

}

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org/pipermail/stringtemplate-interest/attachments/20090317/661158de/attachment-0001.html 


More information about the stringtemplate-interest mailing list