ฉันเข้าใจความแตกต่างระหว่างString
และStringBuilder
( StringBuilder
ไม่แน่นอน) แต่มีประสิทธิภาพแตกต่างกันมากระหว่างทั้งสองหรือไม่
โปรแกรมที่ฉันกำลังใช้งานมีสตริงตัวเรือนจำนวนมากต่อท้าย (500+) ใช้StringBuilder
ตัวเลือกที่ดีกว่าไหม?
ฉันเข้าใจความแตกต่างระหว่างString
และStringBuilder
( StringBuilder
ไม่แน่นอน) แต่มีประสิทธิภาพแตกต่างกันมากระหว่างทั้งสองหรือไม่
โปรแกรมที่ฉันกำลังใช้งานมีสตริงตัวเรือนจำนวนมากต่อท้าย (500+) ใช้StringBuilder
ตัวเลือกที่ดีกว่าไหม?
คำตอบ:
ใช่ความแตกต่างด้านประสิทธิภาพนั้นสำคัญมาก ดูบทความ KB " วิธีการปรับปรุงประสิทธิภาพการต่อสตริงใน Visual C # "
ฉันพยายามเขียนโค้ดเพื่อความชัดเจนก่อนเสมอจากนั้นจึงปรับประสิทธิภาพให้เหมาะสมในภายหลัง นั่นง่ายกว่าทำอย่างอื่นเลย! อย่างไรก็ตามเมื่อเห็นความแตกต่างด้านประสิทธิภาพอย่างมากในแอปพลิเคชันของฉันระหว่างสองแอพนี้ตอนนี้ฉันคิดอีกครั้งอย่างรอบคอบมากขึ้น
โชคดีที่มันค่อนข้างตรงไปตรงมาในการเรียกใช้การวิเคราะห์ประสิทธิภาพบนโค้ดของคุณเพื่อดูว่าคุณใช้เวลาStringBuilder
อยู่ที่ไหน
เพื่อชี้แจงสิ่งที่กิลเลียนพูดเกี่ยวกับสาย 4 ถ้าคุณมีสิ่งนี้:
string a,b,c,d;
a = b + c + d;
จากนั้นมันจะเร็วขึ้นโดยใช้สตริงและตัวดำเนินการบวก นี่เป็นเพราะ (เช่น Java, ตามที่ Eric ชี้ให้เห็น), มันใช้ StringBuilder ภายในโดยอัตโนมัติ (ที่จริงแล้ว, มันใช้ primitive ที่ StringBuilder ใช้เช่นกัน)
อย่างไรก็ตามหากสิ่งที่คุณกำลังทำอยู่ใกล้กับ:
string a,b,c,d;
a = a + b;
a = a + c;
a = a + d;
จากนั้นคุณต้องใช้ StringBuilder อย่างชัดเจน .Net ไม่ได้สร้าง StringBuilder ที่นี่โดยอัตโนมัติเพราะมันจะไม่มีจุดหมาย ในตอนท้ายของแต่ละบรรทัด "a" จะต้องเป็นสตริง (ไม่เปลี่ยนรูป) ดังนั้นมันจะต้องสร้างและกำจัด StringBuilder ในแต่ละบรรทัด สำหรับความเร็วคุณต้องใช้ StringBuilder เดียวกันจนกว่าคุณจะสร้างเสร็จ:
string a,b,c,d;
StringBuilder e = new StringBuilder();
e.Append(b);
e.Append(c);
e.Append(d);
a = e.ToString();
a
เป็นตัวแปรท้องถิ่นและวัตถุมันอ้างอิงไม่ได้รับการกำหนดให้กับตัวแปรอื่น ๆ บางคน (ที่อาจจะเข้าถึงได้ให้กับหัวข้ออื่น) เพิ่มประสิทธิภาพที่ดีสามารถกำหนดได้ว่าa
จะไม่เข้าถึงได้จากรหัสอื่น ๆระหว่างขั้นตอนนี้ สาย; เฉพาะมูลค่าสุดท้ายของa
เรื่อง a = b + c + d;
ดังนั้นจึงสามารถรักษาบรรดาสามบรรทัดของรหัสราวกับว่าพวกเขาเขียน
StringBuilder จะดีกว่าถ้าคุณทำหลายลูปหรือส้อมในรหัสผ่านของคุณ ... อย่างไรก็ตามสำหรับประสิทธิภาพของ PURE หากคุณสามารถหลีกเลี่ยงได้ด้วยการประกาศสตริงเดี่ยวมันก็เป็นสิ่งที่มีประสิทธิภาพมากกว่า
ตัวอย่างเช่น:
string myString = "Some stuff" + var1 + " more stuff"
+ var2 + " other stuff" .... etc... etc...;
มีประสิทธิภาพมากกว่า
StringBuilder sb = new StringBuilder();
sb.Append("Some Stuff");
sb.Append(var1);
sb.Append(" more stuff");
sb.Append(var2);
sb.Append("other stuff");
// etc.. etc.. etc..
ในกรณีนี้ StringBuild อาจถูกพิจารณาว่าสามารถบำรุงรักษาได้มากกว่า แต่ไม่ได้มีประสิทธิภาพมากกว่าการประกาศสตริงเดี่ยว
9 ครั้งจาก 10 แม้ว่า ... ใช้ตัวสร้างสตริง
ในหมายเหตุด้าน: string + var ยังมีประสิทธิภาพมากกว่าวิธีการ string.Format (โดยทั่วไป) ที่ใช้ StringBuilder ภายใน (เมื่อมีข้อสงสัย ... ตรวจสอบตัวสะท้อนแสง!)
ตัวอย่างง่ายๆที่แสดงให้เห็นถึงความแตกต่างของความเร็วเมื่อใช้การString
ต่อข้อมูล VS StringBuilder
:
System.Diagnostics.Stopwatch time = new Stopwatch();
string test = string.Empty;
time.Start();
for (int i = 0; i < 100000; i++)
{
test += i;
}
time.Stop();
System.Console.WriteLine("Using String concatenation: " + time.ElapsedMilliseconds + " milliseconds");
ผลลัพธ์:
ใช้การเรียงต่อกันสตริง: 15423 มิลลิวินาที
StringBuilder test1 = new StringBuilder();
time.Reset();
time.Start();
for (int i = 0; i < 100000; i++)
{
test1.Append(i);
}
time.Stop();
System.Console.WriteLine("Using StringBuilder: " + time.ElapsedMilliseconds + " milliseconds");
ผลลัพธ์:
ใช้ StringBuilder: 10 มิลลิวินาที
เป็นผลให้การทำซ้ำครั้งแรกใช้เวลา 15423 มิลลิวินาทีในขณะที่การทำซ้ำครั้งที่สองใช้StringBuilder
เวลา 10 มิลลิวินาที
ฉันคิดว่าการใช้StringBuilder
เร็วกว่ามากเร็วกว่ามาก
การเปรียบเทียบนี้แสดงให้เห็นว่าการต่อข้อมูลแบบปกตินั้นเร็วกว่าเมื่อรวม 3 หรือน้อยกว่าสตริง
http://www.chinhdo.com/20070224/stringbuilder-is-not-always-faster/
StringBuilder สามารถทำการปรับปรุงที่สำคัญมากในการใช้หน่วยความจำโดยเฉพาะอย่างยิ่งในกรณีของคุณเพิ่ม 500 สายเข้าด้วยกัน
ลองพิจารณาตัวอย่างต่อไปนี้:
string buffer = "The numbers are: ";
for( int i = 0; i < 5; i++)
{
buffer += i.ToString();
}
return buffer;
เกิดอะไรขึ้นในความทรงจำ สตริงต่อไปนี้ถูกสร้างขึ้น:
1 - "The numbers are: "
2 - "0"
3 - "The numbers are: 0"
4 - "1"
5 - "The numbers are: 01"
6 - "2"
7 - "The numbers are: 012"
8 - "3"
9 - "The numbers are: 0123"
10 - "4"
11 - "The numbers are: 01234"
12 - "5"
13 - "The numbers are: 012345"
โดยการเพิ่มหมายเลขห้าเหล่านี้ไปยังจุดสิ้นสุดของสตริงเราสร้างวัตถุสตริง 13 รายการ! และ 12 คนนั้นไร้ประโยชน์! ว้าว!
StringBuilder แก้ไขปัญหานี้ ไม่ใช่ "สตริงที่ไม่แน่นอน" ตามที่เรามักจะได้ยิน ( สตริงทั้งหมดใน. NET จะไม่เปลี่ยนรูป ) มันทำงานได้โดยเก็บบัฟเฟอร์ภายในอาร์เรย์ของถ่าน Calling Append () หรือ AppendLine () เพิ่มสตริงลงในพื้นที่ว่างที่ท้ายอาร์เรย์ char; ถ้าอาร์เรย์มีขนาดเล็กเกินไปมันจะสร้างอาร์เรย์ใหม่ที่ใหญ่กว่าและคัดลอกบัฟเฟอร์ที่นั่น ดังนั้นในตัวอย่างข้างต้น StringBuilder อาจต้องการเพียงอาเรย์เดียวที่มีทั้งหมด 5 ส่วนเพิ่มเติมในสตริง - ขึ้นอยู่กับขนาดของบัฟเฟอร์ คุณสามารถบอก StringBuilder ได้ว่าบัฟเฟอร์ควรมีขนาดเท่าใดใน Constructor
i.ToString()
พวกเขามาจาก ดังนั้นด้วย StringBuilder คุณยังต้องสร้าง 6 + 1 สาย; มันลดการสร้าง 13 สายเพื่อสร้าง 7 สาย แต่นั่นก็ยังเป็นวิธีที่ผิดในการดู; การสร้างสตริงตัวเลขหกตัวนั้นไม่เกี่ยวข้องกัน Bottom line: คุณไม่ควรพูดถึงหกสายที่สร้างโดยi.ToString()
; พวกเขาไม่ได้เป็นส่วนหนึ่งของการเปรียบเทียบประสิทธิภาพ
ใช่StringBuilder
ให้ประสิทธิภาพที่ดีขึ้นในขณะที่ทำการดำเนินการซ้ำผ่านสายอักขระ String
มันเป็นเพราะการเปลี่ยนแปลงทั้งหมดที่จะทำเช่นเดียวเพื่อที่จะสามารถประหยัดเวลาได้มากแทนการสร้างอินสแตนซ์ใหม่เช่น
String
System
เนมสเปซStringBuilder
(สตริงที่ไม่แน่นอน)
System.Text
เนมสเปซขอแนะนำบทความม็อบ dotnet: String Vs StringBuilder ใน C #
คำถาม Stack Overflow ที่เกี่ยวข้อง: ความผันแปรของสตริงเมื่อสตริงไม่เปลี่ยนแปลงใน C #? .
String Vs String Builder:
สิ่งแรกที่คุณต้องรู้ว่าในการประกอบสองชั้นนี้มีชีวิตอยู่ที่ไหน?
ดังนั้น,
สตริงมีอยู่ในSystem
เนมสเปซ
และ
StringBuilderมีอยู่ในSystem.Text
เนมสเปซ
สำหรับการประกาศสตริง :
คุณต้องรวมSystem
เนมสเปซ อะไรแบบนี้
Using System;
และ
สำหรับการประกาศStringBuilder :
คุณต้องรวมSystem.text
เนมสเปซ อะไรแบบนี้
Using System.text;
มาคำถามที่แท้จริง
ข้อแตกต่างระหว่างstring & StringBuilderคืออะไร
ความแตกต่างที่สำคัญระหว่างสองสิ่งนี้คือ:
สตริงไม่เปลี่ยนรูป
และ
StringBuilderไม่แน่นอน
ดังนั้นตอนนี้ให้พูดคุยถึงความแตกต่างระหว่างไม่เปลี่ยนรูปและไม่แน่นอน
ไม่แน่นอน::หมายถึง Changable
ไม่เปลี่ยนรูป::หมายถึงไม่สามารถเปลี่ยนแปลงได้
ตัวอย่างเช่น:
using System;
namespace StringVsStrigBuilder
{
class Program
{
static void Main(string[] args)
{
// String Example
string name = "Rehan";
name = name + "Shah";
name = name + "RS";
name = name + "---";
name = name + "I love to write programs.";
// Now when I run this program this output will be look like this.
// output : "Rehan Shah RS --- I love to write programs."
}
}
}
ดังนั้นในกรณีนี้เราจะเปลี่ยนวัตถุเดียวกัน 5 เท่า
ดังนั้นคำถามที่ชัดเจนคือ! เกิดอะไรขึ้นภายใต้ประทุนเมื่อเราเปลี่ยนสายเดียวกัน 5 ครั้ง
นี่คือสิ่งที่เกิดขึ้นเมื่อเราเปลี่ยนสตริงเดียวกัน 5 ครั้ง
ลองดูที่รูป
ชี้แจง:
เมื่อเราเริ่มต้นตัวแปร "ชื่อ" นี้เป็น "Rehan" เช่นstring name = "Rehan"
ตัวแปรนี้ถูกสร้างขึ้นในสแต็ก "ชื่อ" และชี้ไปที่ค่า "Rehan" หลังจากเรียกใช้งานบรรทัดนี้: "name = name +" Shah "ตัวแปรอ้างอิงไม่ได้ชี้ไปที่วัตถุ" Rehan "อีกต่อไปตอนนี้มันชี้ไปที่" Shah "และอื่น ๆ
ดังนั้นstring
ความหมายที่เปลี่ยนไม่ได้คือเมื่อเราสร้างวัตถุในหน่วยความจำเราจะไม่สามารถเปลี่ยนวัตถุได้
ดังนั้นเมื่อเราทำการดัดแปลงname
ตัวแปรวัตถุก่อนหน้ายังคงอยู่ในหน่วยความจำและวัตถุสตริงใหม่จะถูกสร้างขึ้น ...
ดังนั้นจากรูปด้านบนเรามีวัตถุห้าชิ้นวัตถุสี่ตัวที่ถูกโยนทิ้งไปพวกมันไม่ได้ใช้เลย พวกเขายังคงอยู่ในความทรงจำและพวกเขาจะใช้จำนวนหน่วยความจำ "ตัวเก็บรวบรวมขยะ" มีหน้าที่รับผิดชอบในการทำให้ทรัพยากรนั้นสะอาดจากหน่วยความจำ
ดังนั้นในกรณีของสตริงเมื่อใดก็ตามที่เราจัดการสตริงซ้ำแล้วซ้ำอีกเรามีวัตถุจำนวนมากที่สร้างขึ้นและยังคงอยู่ในหน่วยความจำ
นี่คือเรื่องราวของ String Variable
ตอนนี้ลองดูที่วัตถุ StringBuilder ตัวอย่างเช่น:
using System;
using System.Text;
namespace StringVsStrigBuilder
{
class Program
{
static void Main(string[] args)
{
// StringBuilder Example
StringBuilder name = new StringBuilder();
name.Append("Rehan");
name.Append("Shah");
name.Append("RS");
name.Append("---");
name.Append("I love to write programs.");
// Now when I run this program this output will be look like this.
// output : "Rehan Shah Rs --- I love to write programs."
}
}
}
ดังนั้นในกรณีนี้เราจะเปลี่ยนวัตถุเดียวกัน 5 เท่า
ดังนั้นคำถามที่ชัดเจนคือ! เกิดอะไรขึ้นภายใต้ประทุนเมื่อเราเปลี่ยน StringBuilder เดียวกัน 5 เท่า
นี่คือสิ่งที่เกิดขึ้นเมื่อเราเปลี่ยน StringBuilder เดียวกัน 5 เท่า
คำอธิบาย: ในกรณีของวัตถุ StringBuilder คุณจะไม่ได้รับวัตถุใหม่ วัตถุเดียวกันจะเปลี่ยนในหน่วยความจำดังนั้นแม้ว่าคุณจะเปลี่ยนวัตถุและพูด 10,000 ครั้งเราก็จะยังคงมีเพียงวัตถุ stringBuilder
คุณไม่มีวัตถุขยะจำนวนมากหรือวัตถุ stringBuilder ที่ไม่ใช่ _referenced เพราะเหตุใดจึงสามารถเปลี่ยนแปลงได้ มันไม่แน่นอนหมายความว่ามันเปลี่ยนแปลงตลอดเวลา?
แตกต่าง:
StringBuilder ลดจำนวนการจัดสรรและการกำหนดค่าใช้จ่ายสำหรับหน่วยความจำเพิ่มเติมที่ใช้ ใช้อย่างถูกต้องสามารถลบความต้องการคอมไพเลอร์เพื่อจัดสรรสตริงที่มีขนาดใหญ่และใหญ่ขึ้นเรื่อย ๆ จนกว่าจะพบผลลัพธ์
string result = "";
for(int i = 0; i != N; ++i)
{
result = result + i.ToString(); // allocates a new string, then assigns it to result, which gets repeated N times
}
เมื่อเทียบกับ
String result;
StringBuilder sb = new StringBuilder(10000); // create a buffer of 10k
for(int i = 0; i != N; ++i)
{
sb.Append(i.ToString()); // fill the buffer, resizing if it overflows the buffer
}
result = sb.ToString(); // assigns once
ประสิทธิภาพของการดำเนินการเชื่อมต่อสำหรับวัตถุ String หรือ StringBuilder ขึ้นอยู่กับความถี่ในการจัดสรรหน่วยความจำที่เกิดขึ้น การดำเนินการเชื่อมต่อสตริงจะจัดสรรหน่วยความจำเสมอในขณะที่การดำเนินการเชื่อมต่อแบบ StringBuilder จะจัดสรรหน่วยความจำเฉพาะถ้าบัฟเฟอร์วัตถุ StringBuilder มีขนาดเล็กเกินไปที่จะรองรับข้อมูลใหม่ ดังนั้นคลาส String จึงเหมาะสำหรับการดำเนินการเรียงต่อกันหากมีการต่อจำนวนคงที่ของวัตถุสตริง ในกรณีดังกล่าวการดำเนินการเรียงต่อกันอาจรวมกันเป็นการดำเนินการเดียวโดยคอมไพเลอร์ วัตถุ StringBuilder จะดีกว่าสำหรับการดำเนินการเชื่อมต่อถ้าจำนวนสตริงโดยพลการจะถูกตัดแบ่ง ตัวอย่างเช่นถ้าวงวนต่อกันเป็นจำนวนสุ่มของสตริงของการป้อนข้อมูลของผู้ใช้
ที่มา: MSDN
StringBuilder
ดีกว่าสำหรับการสร้างสตริงจากค่าที่ไม่คงที่จำนวนมาก
หากคุณกำลังสร้างสตริงจากค่าคงที่จำนวนมากเช่นค่าหลายบรรทัดในเอกสาร HTML หรือ XML หรือกลุ่มข้อความอื่น ๆ คุณสามารถหนีไปได้ด้วยการต่อท้ายสตริงเดียวกันเพราะคอมไพเลอร์เกือบทั้งหมดทำ "การพับอย่างต่อเนื่อง" ซึ่งเป็นกระบวนการลดทรีการแยกวิเคราะห์เมื่อคุณมีการจัดการอย่างต่อเนื่องมากมาย (มันยังใช้เมื่อคุณเขียนบางอย่างเช่นint minutesPerYear = 24 * 365 * 60
) และสำหรับกรณีง่าย ๆ ที่มีค่าไม่คงที่ต่อท้ายซึ่งกันและกันคอมไพเลอร์. NET จะลดรหัสของคุณให้คล้ายกับสิ่งที่StringBuilder
ทำ
StringBuilder
แต่เมื่อผนวกของคุณไม่สามารถจะลดลงไปสิ่งที่ง่ายโดยรวบรวมคุณจะต้องการ เมื่อ fizch ชี้ให้เห็นว่ามีแนวโน้มที่จะเกิดขึ้นภายในวง
ฉันเชื่อว่า StringBuilder เร็วขึ้นถ้าคุณมีมากกว่า 4 สายคุณต้องผนวกเข้าด้วยกัน นอกจากนี้ยังสามารถทำสิ่งที่ยอดเยี่ยมเช่น AppendLine
ใน. NET, StringBuilder ยังเร็วกว่าการผนวกสตริง ฉันค่อนข้างมั่นใจว่าใน Java พวกเขาเพิ่งสร้าง StringBuffer ภายใต้ประทุนเมื่อคุณต่อท้ายสตริงดังนั้นจึงไม่มีความแตกต่างจริงๆ ฉันไม่แน่ใจว่าทำไมพวกเขายังไม่ได้ทำใน. NET
ใช้สายสำหรับการเรียงต่อกันจะนำไปสู่ความซับซ้อน runtime O(n^2)
ในคำสั่งของ
หากคุณใช้ a StringBuilder
จะมีการคัดลอกหน่วยความจำน้อยกว่าที่ต้องทำ ด้วยการที่StringBuilder(int capacity)
คุณสามารถเพิ่มประสิทธิภาพถ้าคุณสามารถประเมินว่าสุดท้ายString
จะเป็นอย่างไร แม้ว่าคุณจะไม่แม่นยำ แต่คุณก็อาจต้องเพิ่มขีดความสามารถStringBuilder
เพียงสองสามครั้งเพื่อช่วยให้ประสิทธิภาพการทำงานดีขึ้น
ฉันได้เห็นประสิทธิภาพที่เพิ่มขึ้นอย่างมากจากการใช้EnsureCapacity(int capacity)
การเรียกเมธอดบนอินสแตนซ์StringBuilder
ก่อนที่จะใช้มันสำหรับที่เก็บสตริง ฉันมักจะเรียกว่าในบรรทัดของรหัสหลังจากการเริ่มต้น มันมีผลเช่นเดียวกับถ้าคุณยกตัวอย่างStringBuilder
เช่นนี้:
var sb = new StringBuilder(int capacity);
การเรียกนี้จัดสรรหน่วยความจำที่จำเป็นก่อนเวลาซึ่งทำให้การจัดสรรหน่วยความจำน้อยลงระหว่างAppend()
การดำเนินการหลายอย่าง คุณต้องคาดเดาความรู้เกี่ยวกับจำนวนหน่วยความจำที่คุณต้องการ แต่สำหรับแอปพลิเคชั่นส่วนใหญ่สิ่งนี้ไม่ควรยากเกินไป ฉันมักจะผิดพลาดในด้านของหน่วยความจำน้อยเกินไป (เรากำลังพูดถึง 1k หรือมากกว่านั้น)
EnsureCapacity
หลังจากเริ่มStringBuilder
ต้น เพียงแค่ยกตัวอย่างเช่นนี้StringBuilder
var sb = new StringBuilder(int capacity)
นอกเหนือจากคำตอบก่อนหน้าสิ่งแรกที่ฉันมักจะทำเมื่อคิดถึงปัญหาเช่นนี้คือการสร้างแอปพลิเคชันทดสอบขนาดเล็ก ภายในแอพนี้ทำการทดสอบการจับเวลาสำหรับทั้งสองสถานการณ์และดูด้วยตัวคุณเองที่เร็วกว่า
IMHO การต่อท้ายรายการสตริง 500+ รายการควรใช้ StringBuilder อย่างแน่นอน
String และ StringBuilder มีทั้งที่ไม่สามารถเปลี่ยนแปลงได้จริง StringBuilder สร้างขึ้นในบัฟเฟอร์ซึ่งทำให้ขนาดของมันสามารถจัดการได้อย่างมีประสิทธิภาพมากขึ้น เมื่อ StringBuilder จำเป็นต้องปรับขนาดคือเมื่อมีการจัดสรรใหม่บนฮีป โดยค่าเริ่มต้นมันมีขนาด 16 ตัวอักษรคุณสามารถตั้งค่านี้ในตัวสร้าง
เช่น.
StringBuilder sb = ใหม่ StringBuilder (50);
การต่อสตริงจะทำให้คุณเสียค่าใช้จ่ายมากขึ้น ใน Java คุณสามารถใช้ StringBuffer หรือ StringBuilder ตามความต้องการของคุณ ถ้าคุณต้องการการซิงโครไนซ์และการใช้เธรดอย่างปลอดภัยให้ไปที่ StringBuffer นี่จะเร็วกว่าการต่อข้อมูลสตริง
หากคุณไม่ต้องการซิงโครไนซ์หรือใช้งานเธรดอย่างปลอดภัยให้ไปที่ StringBuilder สิ่งนี้จะเร็วกว่าการต่อข้อมูลสตริงและเร็วกว่า StringBuffer เนื่องจากไม่มีค่าใช้จ่ายในการซิงโครไนซ์
StringBuilder น่าจะดีกว่า เหตุผลก็คือมันจัดสรรพื้นที่มากกว่าที่จำเป็นในปัจจุบัน (คุณกำหนดจำนวนตัวอักษร) เพื่อออกจากห้องสำหรับการผนวกในอนาคต ในอนาคตเหล่านั้นจะผนวกเข้ากับบัฟเฟอร์ปัจจุบันไม่จำเป็นต้องมีการจัดสรรหน่วยความจำหรือการรวบรวมขยะซึ่งอาจมีราคาแพง โดยทั่วไปแล้วฉันใช้ StringBuilder สำหรับการเรียงสตริงที่ซับซ้อนหรือการจัดรูปแบบหลายรูปแบบจากนั้นแปลงเป็นสตริงปกติเมื่อข้อมูลเสร็จสมบูรณ์และฉันต้องการวัตถุที่ไม่เปลี่ยนรูปอีกครั้ง
หากคุณกำลังต่อเชื่อมสตริงจำนวนมากใช้ StringBuilder เมื่อคุณต่อสตริงเข้าด้วยกันคุณจะสร้างสตริงใหม่ทุกครั้งโดยใช้หน่วยความจำมากขึ้น
อเล็กซ์
ตามกฎทั่วไปของหัวแม่มือถ้าฉันต้องตั้งค่าสตริงมากกว่าหนึ่งครั้งหรือหากมีผนวกกับสตริงนั้นจะต้องมีการสร้างสตริง ฉันเคยเห็นแอปพลิเคชันที่ฉันเคยเขียนในอดีตก่อนที่จะเรียนรู้เกี่ยวกับผู้สร้างสตริงที่มีการพิมพ์หน่วยความจำขนาดใหญ่ที่ดูเหมือนว่าจะเติบโตและเติบโต การเปลี่ยนโปรแกรมเหล่านี้เพื่อใช้ตัวสร้างสตริงลดการใช้หน่วยความจำลงอย่างมาก ตอนนี้ฉันสาบานโดยผู้สร้างสตริง
วิธีการของฉันคือการใช้ StringBuilder ตลอดเวลาเมื่อทำการต่อสาย 4 ตัวหรือมากกว่านั้นหรือเมื่อฉันไม่รู้ว่าการต่อเรียงจะเกิดขึ้นได้อย่างไร
StringBuilder
มีประสิทธิภาพมากขึ้นอย่างมีนัยสำคัญ แต่คุณจะไม่เห็นประสิทธิภาพนั้นเว้นแต่ว่าคุณกำลังทำการแก้ไขสตริงจำนวนมาก
ด้านล่างนี้เป็นโค้ดสั้น ๆ เพื่อเป็นตัวอย่างของประสิทธิภาพ อย่างที่คุณเห็นคุณเริ่มเห็นการเพิ่มขึ้นอย่างมากเมื่อคุณทำซ้ำจำนวนมาก
อย่างที่คุณเห็นการทำซ้ำ 200,000 ครั้งใช้เวลา 22 วินาทีในขณะที่การใช้ซ้ำ 1 ล้านครั้งStringBuilder
นั้นเกือบจะทันที
string s = string.Empty;
StringBuilder sb = new StringBuilder();
Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());
for (int i = 0; i <= 50000; i++)
{
s = s + 'A';
}
Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();
Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());
for (int i = 0; i <= 200000; i++)
{
s = s + 'A';
}
Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();
Console.WriteLine("Beginning Sb append at " + DateTime.Now.ToString());
for (int i = 0; i <= 1000000; i++)
{
sb.Append("A");
}
Console.WriteLine("Finished Sb append at " + DateTime.Now.ToString());
Console.ReadLine();
ผลลัพธ์ของโค้ดด้านบน:
String เริ่มต้น + ที่ 28/01/2013 16:55:40
สิ้นสุด String + ที่ 28/01/2013 16:55:40
String เริ่มต้น + ที่ 28/01/2013 16:55:40
สิ้นสุด String + ที่ 28/01/2013 16:56:02
การเริ่มต้น Sb ต่อท้ายเวลา 28/01/2013 16:56:02
เสร็จแล้ว Sb ต่อท้ายที่ 28/01/2013 16:56:02
StringBuilder จะทำงานได้ดีขึ้นจากจุดตั้งหน่วยความจำ สำหรับการประมวลผลความแตกต่างในช่วงเวลาของการดำเนินการอาจจะเล็กน้อย