亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

.Net 中字符串性能

系統(tǒng) 1776 0

Introduction

你在代碼中處理字符串的方法可能會(huì)對(duì)性能產(chǎn)生令人吃驚的影響。在本文中,我需要考慮兩個(gè)由于使用字符串而產(chǎn)生的問(wèn)題:臨時(shí)字符串變量的使用和字符串連接。

Background

每個(gè)項(xiàng)目都有需要你為其考慮編碼標(biāo)準(zhǔn)的時(shí)候。使用 FxCop 是一個(gè)好的開(kāi)始。我最喜愛(ài)的一組 FxCop 規(guī)則是“性能”那組。

于是,我就用 FxCop 來(lái)檢查我的項(xiàng)目并發(fā)現(xiàn)一系列的字符串問(wèn)題。我必須承認(rèn)一件事:我經(jīng)常遇到與 C# 的不可變(immutable)的字符串有關(guān)的問(wèn)題。當(dāng)我看到 myString.ToUpper() 時(shí),我經(jīng)常都會(huì)忘記它并不是改變 myString 的內(nèi)容而是返回一整個(gè)全新的字符串(這是由于 C# 中字符串是不可變的)。

我對(duì)代碼進(jìn)行一番修正以便去掉 FxCop 的警告,接著我就發(fā)現(xiàn)代碼的確比之前快了。我決定開(kāi)展調(diào)查,而最終我會(huì)寫出上面那些測(cè)試的代碼的。

Using the code

測(cè)試的代碼很簡(jiǎn)單。一個(gè)控制臺(tái)程序調(diào)用四個(gè)測(cè)試方法,其中每個(gè)方法執(zhí)行一種字符串處理例程 1000 次(整個(gè)執(zhí)行時(shí)間已經(jīng)足夠長(zhǎng)以便看出其中的性能差別了)。

這四個(gè)測(cè)試方法被分成兩組,每組兩個(gè)。第一組比較兩個(gè)方法,它們用于非大小寫敏感(case-insensitive)的字符串比較。

String Comparison and Temporary String Creation

第一個(gè)測(cè)試?yán)淌且粋€(gè)蹩腳的非大小寫敏感的字符串比較。用于比較的例程的代碼是:

static bool BadCompare( string stringA, string stringB)
{
return (stringA.ToUpper()==stringB.ToUpper());
}

對(duì)于這段代碼,F(xiàn)xCop 給出如下的建議:

"StringCompareTest.BadCompare(String, String):Boolean calls String.op_Equality(String, String):Boolean after converting 'stack1', a local, to upper or lowercase. If possible, eliminate the string creation and call the overload of String.Compare that performs a case-insensitive comparison."

這項(xiàng)建議的意思是每次對(duì) ToUpper() 的調(diào)用都會(huì)創(chuàng)造一個(gè)臨時(shí)字符串,而這個(gè)臨時(shí)字符串是由垃圾收集器來(lái)創(chuàng)建和管理的。這需要額外的時(shí)間和使用更多的內(nèi)存。 String.Compare 方法(相對(duì)來(lái)說(shuō))更加高效。

第二個(gè)測(cè)試?yán)淌褂?String.Compare :

static bool GoodCompare( string stringA, string stringB)
{
return ( string .Compare(stringA,stringB, true ,System.Globalization.CultureInfo.CurrentCulture)==0);
}

這個(gè)方法防止多余的臨時(shí)字符串的創(chuàng)建。

根據(jù) nprof 的分析結(jié)果 , GoodCompare 的執(zhí)行時(shí)間只占代碼總執(zhí)行時(shí)間的 1.69%, 而 BadCompare 的執(zhí)行時(shí)間則占總執(zhí)行時(shí)間的 5.50% 。

因此 String.Compare 方法比 ToUpper 方法快了三倍有余。如果你的代碼您執(zhí)行了很多字符串的比較(尤其是在循環(huán)里面執(zhí)行),使用 String.Compare 能(使你的代碼在性能上)有較大的改善。

String Concatenation inside a loop

最后那對(duì)測(cè)試?yán)淘O(shè)想字符串的連接是在一個(gè)循環(huán)里面進(jìn)行的。

“蹩腳”的測(cè)試?yán)痰拇a如下:

static string BadConcatenate( string []items)
{
string strRet= string .Empty;

foreach ( string item in items)
{
strRet+=item;
}


return strRet;
}

當(dāng) FxCop 看到這段代碼,它就會(huì)很憤怒,甚至用紅色標(biāo)記這項(xiàng)被破的規(guī)條! FxCop 這樣說(shuō)道:

"Change StringCompareTest.BadConcatenate(String[]):String to use StringBuilder instead of String.Concat or +="

“優(yōu)良”的測(cè)試?yán)痰拇a如下:

static string GoodConcatenate( string []items)
{
System.Text.StringBuilderbuilder=
new System.Text.StringBuilder();

foreach ( string item in items)
{
builder.Append(item);
}


return builder.ToString();
}

這段代碼幾乎被用作展示 System.Text.StringBuilder 的用法的首選例子。蹩腳的代碼的問(wèn)題是創(chuàng)建了過(guò)多的臨時(shí)字符串。由于字符串的不可變特性,連接操作符(+=)實(shí)際上用原來(lái)那兩個(gè)字符串來(lái)創(chuàng)建一個(gè)新的字符串,然后把原來(lái)的字符串實(shí)例指向這個(gè)新的字符串。

但是,依據(jù) nprof 來(lái)研究代碼性能,我們發(fā)現(xiàn)運(yùn)行 BadConcatenate 只需總執(zhí)行時(shí)間的 5.67% ,而 GoodConcatenate 則是 22.09% 。也就是說(shuō):

使用 StringBuilder 耗費(fèi)的時(shí)間幾乎是簡(jiǎn)單的字符串連接的四倍!

為什么呢?

部分原因在于這個(gè)測(cè)試的設(shè)計(jì)——連接例程僅僅連接了十個(gè)簡(jiǎn)短的字符串。 StringBuilder 是一個(gè)比簡(jiǎn)單的不可變的字符串類更復(fù)雜的類,因此創(chuàng)建一個(gè) StringBuilder 比起進(jìn)行十個(gè)簡(jiǎn)單的字符串連接在性能上是昂貴很多的。

我重復(fù)地做不同數(shù)目的字符串連接的測(cè)試,并且發(fā)現(xiàn)以下結(jié)果:

注意:這里所顯示的數(shù)值是測(cè)試?yán)痰膱?zhí)行時(shí)間占總執(zhí)行時(shí)間的百分比(%)。 GoodConcatenate 實(shí)際上并沒(méi)有快很多,但與 BadConcatenate 比卻相對(duì)地快了。

因此, StringBuilder 通常只有在你要連接的字符串?dāng)?shù)目超過(guò) 600 時(shí)才會(huì)顯示出真正的性能優(yōu)勢(shì)。

當(dāng)然,另外一個(gè)使用 StringBuilder 的原因就是是內(nèi)存的分配。使用 CLRProfiler 生成下面這個(gè)連接 100 個(gè)簡(jiǎn)單字符串時(shí)內(nèi)存使用情況的時(shí)序圖:

標(biāo)記為“A”的區(qū)域顯示了 BadConcatenate 在內(nèi)存分配和釋放上的效果。被分配內(nèi)存的最大值迅速增加,并伴有大數(shù)量的垃圾收集的發(fā)生(該區(qū)域有大約 215 次垃圾收集)。

緊隨在“A”區(qū)后面的區(qū)域顯示了 GoodConcatenate 的內(nèi)存輪廓。被分配內(nèi)存的最大值增量較少,且伴隨著非常少的垃圾收集(該區(qū)域有大致 60 次垃圾收集)。

所以在某些情況下使用 StringBuilder 類并不會(huì)(使你的代碼運(yùn)行得)更快 , 但它對(duì)垃圾收集器是友好的。

Conclusions

使用 String.Compare 方法進(jìn)行非大小寫敏感的字符串比較。這樣更快。而且代碼優(yōu)雅和簡(jiǎn)單。

僅當(dāng)你在一個(gè)循環(huán)里進(jìn)行超過(guò) 600 次的字符串連接時(shí),使用 StringBuilder 來(lái)獲得更好的速度。這里需要提醒的是,你所處理的字符串的長(zhǎng)度也會(huì)影響最終的速度,同樣會(huì)影響垃圾收集器的效果,所以你應(yīng)該根據(jù)你實(shí)際的代碼具體問(wèn)題具體分析。

Points of Interest

令我驚訝的是,在真實(shí)世界運(yùn)用正確的代碼字符串操作方法的還是很不同(雖然我們已在當(dāng)前的項(xiàng)目中進(jìn)行了很多字符串的比較和連接)。

FxCop 的性能規(guī)則是發(fā)現(xiàn)潛在低性能代碼的好起點(diǎn),并能指導(dǎo)你進(jìn)行一些簡(jiǎn)易修正來(lái)改善代碼性能。這里所討論的兩個(gè)問(wèn)題都被 FxCop 標(biāo)記為“NON-BREAKING”,這是指改動(dòng)不應(yīng)破壞依賴于被改動(dòng)代碼的代碼。認(rèn)為為改善性能而做的改動(dòng)都是“NON-BREAKING”則是沒(méi)頭腦的想法。

Further Considerations By Allen Lee

使用 StringBuilder 來(lái)處理字符串的連接應(yīng)該是絕大多數(shù) .NET 開(kāi)發(fā)人員的共識(shí)了。但你有否曾經(jīng)懷疑過(guò)這一經(jīng)驗(yàn)原則的適用性是否真如想象中那么廣泛呢?讀過(guò)本文后,或許你已經(jīng)意識(shí)到這是個(gè)適度的問(wèn)題。對(duì)小規(guī)模的字符串連接使用 StringBuilder 所帶來(lái)的改善根本不足以抵償因 StringBuilder 本身的復(fù)雜性所產(chǎn)生的開(kāi)銷;只有當(dāng)連接規(guī)模達(dá)到臨界規(guī)模,兩者才能相互抵償從而達(dá)至平衡。

對(duì)于實(shí)際的代碼,一個(gè)可供使用的臨界規(guī)模值可能是必需的,尤其是在受限系統(tǒng)上進(jìn)行開(kāi)發(fā)。你可能因?yàn)閷?duì)影響臨界規(guī)模的因素有所了解而懷疑作者在這里所給出的數(shù)字。或許本文用于測(cè)試的設(shè)計(jì)顯得有點(diǎn)簡(jiǎn)單以至于未必能使更多的人信服,但你的確透過(guò)本文了解到 StringBuilder 并不是任何情況都適用的。由于影響臨界規(guī)模的因素總有可能發(fā)生變化,你不可能找到一個(gè)對(duì)任何情況都適用的確定的臨界規(guī)模值。你應(yīng)該為你的代碼量身訂造一個(gè),并隨時(shí)做好調(diào)整的準(zhǔn)備(因?yàn)樽兓偸谴嬖诘模灰阏娴哪敲丛谝膺@方面的性能影響。作為一個(gè)開(kāi)始,你可以以作者在本文所提到的那個(gè)數(shù)字作為一個(gè)參照基礎(chǔ),并就具體的情況進(jìn)行微調(diào),直到你滿意為止。

.Net 中字符串性能


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 色综合网站在线 | 中文字幕精品在线视频 | 日日噜噜夜夜狠狠久久aⅴ 日日噜噜夜夜狠狠久久丁香 | 亚洲天堂爱爱 | 日韩精品一区二区三区 在线观看 | 奇米色偷偷 | 国产精品爱久久 | 麻豆久久婷婷综合五月国产 | 亚洲人成亚洲精品 | 毛片真人毛毛片毛片 | 精品亚洲一区二区三区 | 99热在线精品免费播放6 | 国产日韩美国成人 | 在线播放福利 | 日日爽天天干 | 久久一区二区三区不卡 | 青青草久热精品视频在线观看 | 久久频 | 国产精品天天干 | 免费高清在线爱做视频 | 天天插天天操天天射 | 色综合综合色综合色综合 | 曰本毛片va看到爽不卡 | 一级特黄一欧美俄罗斯毛片 | 天天综合在线观看 | 久久这里精品青草免费 | 美女个护士一级毛片亚洲 | 国产欧美日韩精品第三区 | 青草福利 | 久久草视频在线 | 日韩亚洲欧洲在线rrrr片 | 四虎在线视频 | 久久永久影院免费 | 亚洲综合色视频在线观看 | 天天干精品 | 8090成人午夜精品 | 久久精品免视国产 | 国产综合一区二区 | 涩涩一区| 大杳蕉伊人狼人久久一本线 | 日韩欧美一区在线观看 |