不管是在 Java 或是 C#,對於 String 這物件應該都不陌生。但如果考量是在字串串接的用途上時, String 的效能可真的就顯得遜色許多。
String 物件一旦在記憶體被配置之後,他就不能夠再改變了,所以他常常被說成是 immutable object。但我們卻很習慣寫成這樣:
三行程式寫完後,請求了三塊新的記憶體配置,也同時浪費了兩塊記憶體。
針對這個問題,Java 提供了 StringBuffer 物件,讓我們可以對字串加加減減,也不會另外再要一塊新的記憶體位址來存放。在這物件當中,Java 還考慮到多執行緒的問題,也就是說,不同的執行緒不會同時對同一個 StringBuffer 物件做新增或是修改的動作,例如當執行緒 A 在使用 「StringBuffer 甲」的時候,執行緒 B 必須等到執行緒 A 完成「StringBuffer 甲」的處理動作 之後才能使用,這就是我們常說的 thread-safe。
對於 Java 所提供的 StringBuffer 物件,針對字串串接的執行校能上,的確可以非常明顯地看到提昇,但一般對程式設計師來說,大部分時機其實可能都不需要考量多執行緒的問題,如果不考慮多執行緒的情況下,減少多餘的判斷處理,是否還有機會再提昇字串串接的效能呢?
果真,在 JDK 1.5. 之後,開始出現了新的物件 StringBuilder ,他與 StringBuffer 的用途幾乎如出一轍,唯一的不同是減少了多執行緒的考量。日後如果只是在寫單一執行緒的程式考量下,StringBuilder 會是較好的選擇。「
StringBuffer vs. StringBuilder performance comparison」文章作者Daniel 針對 StringBuilder 與 StringBuffer 兩者間的效能寫了一段簡單的程式來比較,而我自己也透過他的程式在自己電腦上得到了下面數據:
從數據上看來, StringBuilder 已經比 StringBuffer 提昇了一倍以上的效能,當然這兩者更遠遠超過 String 的字串串接。
同樣的情況,也出現在 微軟的 C# 裡。在字串串接的情況下, StringBuilder 遠比 String 的效能提昇很多,唯一讓我不解的,是這次微軟的身上少了 StringBuffer 的味道...,我很認真的想知道這次微軟為何沒收錄 StringBuffer 這物件,但迄今依舊無解。而微軟的 StringBuilder,同樣也是不考慮多執行緒,可以在微軟的官方文件「
StringBuilder Class」看到 Thread Safety 的聲明:
Any public static (Shared in Visual Basic) members of this type are thread safe.
Any instance members are not guaranteed to be thread safe.
可從上面申明中知道,C# 裡面的 StringBuilder 並不是 thread-safe。
另一個有趣的地方,是從
JDK 釋出的時程來看看,彷彿 .net 在 2003年時釋出的 .net 1.1, 已經比 Java 更早公佈 StringBuilder 物件了!
經由這一次的整理,可以知道 String 在字串串接上所面臨的效能瓶頸,並透過 Daniel 的程式在定量上可以得到支撐。此外,也可以更清楚去分別依據是否為單一執行緒來正確抉擇 StringBuilder 或 StringBuffer。
參考:
01:
StringBuffer vs. StringBuilder performance comparison
02:
StringBuilder Class
03:
Java JDK (Java Development Kit) Releases Dates and Release Differences
04:
Java SE 6全方位學習
05:
StringBuilder和StringBuffer的差別及清空內容方式
06:
StringBuilder vs StringBuffer
07:
Why use StringBuilder? StringBuffer can work with multiple thread as well as one thread?
08:
StringBuffer and StringBuilder
09:
Is the C# '??' operator thread safe?
10:
如何:增進 Visual C# .NET 中的字串串連效能
11:
Daniel 簡單測試程式