铁匠

做人要低调
随笔 - 139, 评论 - 611 , 引用 - 185

导航

公告

文章分类

存档

随笔分类

相册

BLOG

网站

论坛

string.format()是否应该多用?

前一阵子,项目中的一个页面每秒只能处理300次,而这个页面的逻辑也不复杂,就是根据条件拼出一个字串然后输出。开始以为这里面逻辑太复杂,所以有问题。不过后面发现了vs里面带了性能分析工具,于是抱着试试看的想法,作了一下性能分析。最后的结果让人大吃一惊:string.format这个操作竟然用掉了一半的时间,为啥它会这么费时间呢?为了真相,我用.net reflector查看了string的实现:

public static string Format(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
    StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));
    builder.AppendFormat(provider, format, args);
    return builder.ToString();
}


很让人吃惊,string.format竟然是调用了StringBuilder的AppendFormat来实现的。再继续根下去(这个源码只是通过IL得来的,可能和原始的不太一样,但是差不多了),注意里面的红色的那句:

public StringBuilder AppendFormat(IFormatProvider provider, string format, params object[] args)
{
    int num3;
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
    char[] chArray = format.ToCharArray(0, format.Length);
    int index = 0;
    int length = chArray.Length;
    char ch = '\0';
    ICustomFormatter formatter = null;
    if (provider != null)
    {
        formatter = (ICustomFormatter) provider.GetFormat(typeof(ICustomFormatter));
    }
Label_004E:
    num3 = index;
    int num4 = index;
    while (index < length)
    {
        ch = chArray[index];
        index++;
        if (ch == '}')
        {
            if ((index < length) && (chArray[index] == '}'))
            {
                index++;
            }
            else
            {
                FormatError();
            }
        }
        if (ch == '{')
        {
            if ((index < length) && (chArray[index] == '{'))
            {
                index++;
            }
            else
            {
                index--;
                break;
            }
        }
        chArray[num4++] = ch;
    }
    if (num4 > num3)
    {
        this.Append(chArray, num3, num4 - num3);
    }
    if (index == length)
    {
        return this;
    }
    index++;
    if (((index == length) || ((ch = chArray[index]) < '0')) || (ch > '9'))
    {
        FormatError();
    }
    int num5 = 0;
    do
    {
        num5 = ((num5 * 10) + ch) - 0x30;
        index++;
        if (index == length)
        {
            FormatError();
        }
        ch = chArray[index];
    }
    while (((ch >= '0') && (ch <= '9')) && (num5 < 0xf4240));
    if (num5 >= args.Length)
    {
        throw new FormatException(Environment.GetResourceString("Format_IndexOutOfRange"));
    }
    while ((index < length) && ((ch = chArray[index]) == ' '))
    {
        index++;
    }
    bool flag = false;
    int num6 = 0;
    if (ch == ',')
    {
        index++;
        while ((index < length) && (chArray[index] == ' '))
        {
            index++;
        }
        if (index == length)
        {
            FormatError();
        }
        ch = chArray[index];
        if (ch == '-')
        {
            flag = true;
            index++;
            if (index == length)
            {
                FormatError();
            }
            ch = chArray[index];
        }
        if ((ch < '0') || (ch > '9'))
        {
            FormatError();
        }
        do
        {
            num6 = ((num6 * 10) + ch) - 0x30;
            index++;
            if (index == length)
            {
                FormatError();
            }
            ch = chArray[index];
        }
        while (((ch >= '0') && (ch <= '9')) && (num6 < 0xf4240));
    }
    while ((index < length) && ((ch = chArray[index]) == ' '))
    {
        index++;
    }
    object arg = args[num5];
    string str = null;
    if (ch == ':')
    {
        index++;
        num3 = index;
        num4 = index;
        while (true)
        {
            if (index == length)
            {
                FormatError();
            }
            ch = chArray[index];
            index++;
            switch (ch)
            {
                case '{':
                    if ((index < length) && (chArray[index] == '{'))
                    {
                        index++;
                    }
                    else
                    {
                        FormatError();
                    }
                    break;

                case '}':
                    if ((index < length) && (chArray[index] == '}'))
                    {
                        index++;
                    }
                    else
                    {
                        index--;
                        if (num4 > num3)
                        {
                            str = new string(chArray, num3, num4 - num3);
                        }
                        goto Label_0253;
                    }
                    break;
            }
            chArray[num4++] = ch;
        }
    }
Label_0253:
    if (ch != '}')
    {
        FormatError();
    }
    index++;
    string str2 = null;
    if (formatter != null)
    {
        str2 = formatter.Format(str, arg, provider);
    }
    if (str2 == null)
    {
        if (arg is IFormattable)
        {
            str2 = ((IFormattable) arg).ToString(str, provider);
        }
        else if (arg != null)
        {
            str2 = arg.ToString();
        }
    }
    if (str2 == null)
    {
        str2 = string.Empty;
    }
    int repeatCount = num6 - str2.Length;
    if (!flag && (repeatCount > 0))
    {
        this.Append(' ', repeatCount);
    }
    this.Append(str2);
    if (flag && (repeatCount > 0))
    {
        this.Append(' ', repeatCount);
    }
    goto Label_004E;
}

发现里面会有new string,这时候会有新的内存分配出现,也就是说string.format会产生很多临时的string对象,这个会费时间,同时也会使GC的工作量增加.既然这里面调用了stringbuilder来实现的,那为啥不直接调用stringbuilder.append来实现。于是我就把原来的实现改成了stringbuilder的append,同时设置它初始容量为我们预期的大小,通过测试,这部分的性能提高了十倍。于是性能问题解决了。

最后,我觉得如果程序的性能很重要,而在这里面又经常有string.format的时候,还是改用stringbuilder.append来实现,虽然麻烦一些,代码也不好看,但是效果还是会很明显的。

发表于 2008年12月8日 3:06

评论

# re: string.format()是否应该多用?

我觉得如果程序的性能很重要,而在这里面又经常有string.format的时候,还是改用stringbuilder.append来实现,虽然麻烦一些,代码也不好看,但是效果还是会很明显的。
2009/10/2 21:16 | 凡客诚品

# printing on a t shirt

I visited lot of site and read lot of article. I am really happy for this post in this site. So i always want to concentrate in this site about different article.
2011/12/9 18:50 | printing on a t shirt

# coach outlet online

The most incredible knack about the coach bag of coach outlet online is that it would excellently please your minds beyond your mind's eye. For example, if you want to become the Angelina Julie, you will immediately need to wear the coach handbag around your shoulder.On establishing contact with a coach outlet hire agency, a few clarifications would need to be put to rest prior to working out a deal.
2012/1/6 11:20 | coach outlet online

# louis vuitton outlet

In the web times, even if you are a noble person on
louis vuitton outlet

, or to real action to prove himself, has been integrated into a new era.If in a foreign country to join the twitter, it is best to join army of micro-Bo;They're not chosen, so one of these ideal for you.For more flexibleness a lot more like these, there are lots of discount 'shoulder' variations outlet
louis vuitton bags

.
http://www.louisvuittonoutletbagsu.com
2012/1/6 11:55 | louis vuitton outlet

# coach outlet online

At the
coach outlet online

you have the largest selection of the day. If you touch the item and like it, keep it in your possession until you make your final decision.In particular, products from
coach factory outlet

with leather design are fashionable, handmade,leading the wave of American pop.It with simple,durable and unique style to win consumers.
http://www.coachoutletonlineusacoach.com
2012/1/6 11:56 | coach outlet online

# coach factory outlet

Welcome to the coach factory outlet store and Enjoy Shopping Here! We promise all the customers to have the superior qualities and low prices.Many people like to go to coach factory online, Some people like to designers and shiny metal or leather coach shoulder bags. However, the majority of women choose to safe the neuter color coach shoulder bags. http://www.coachfactoryoutletlove.com
2012/1/6 13:22 | coach factory outlet

# louis vuitton sale

There must be one louis vuitton vernis that is sure to fit your style. louis vuitton sale provide Louis Vuitton belt for men has royal purple lining, which could burnish whatever clothes.As we show below, louis vuitton outlet have a number of Louis Vuitton Earrings, louis vuitton replica handbags, in different styles for your selection.
http://www.louisvuittonoutletsaletime.com
2012/1/6 13:22 | louis vuitton sale

# louis vuitton uk

As we know,
louis vuitton uk

as we can imagine are a little expensive but are of good quality like the brand Coach. It's really a good choice to shopping in Louis Vuitton outlet.
louis vuitton

Outlets offer famous classic brand for LV,Channel, with perfect service.So become to the VIP soon.They offer more new styles,like LV purses,LV wallets etc. And are tested by product quality monitoring center .
http://www.louisvuitton-ukoutlet.org.uk
2012/1/6 13:28 | louis vuitton uk

# coach outlet store

Coach Outlet Store vision system is a visual enjoy, is a visual art. The particular design has been integrated function and the element of elegancy, then show you an exquisite and excellent product. You need not worry about the quality of the coach outlet store online for sale now. The Coach brand is famous for the perfect products.

2012/1/6 14:08 | coach outlet store

# coach outlet

if your dream is to look like a million bucks for a mere several dollars, then our coach outlet store is the Jiminy Cricket of your existence. to obtain coach outlet online in Hainan is amongst the brand new darling from residential holiday makers.


2012/1/6 14:09 | coach outlet

# coach factory outlet

Coach Factory Outlet has a big heart and a healthy appetite, and a wicked swing with a chainsaw.
2012/1/7 16:38 | coach factory outlet

# louis vuitton uk

The latest fashion collection contains those bags suitable to be worn in both casual and formal environment.
2012/1/7 16:38 | louis vuitton uk

Post Comment

主题  
姓名  
主页
校验码  
内容   
京ICP备 05050892号