2011-09-25 29 views
5

Khi tôi trống rỗng StringBuilder với dung lượng 5 và tôi viết "hello, world!" với nó, tiêu chuẩn C# có chỉ định dung lượng mới của StringBuilder không? Tôi có một bộ nhớ mơ hồ rằng nó gấp đôi chiều dài của chuỗi mới (để tránh thay đổi dung lượng với mỗi chuỗi nối mới).Dung lượng của StringBuilder thay đổi như thế nào?

+4

Điều này không được quy định trong bất kỳ tiêu chuẩn nào – BrokenGlass

+0

StringBuilder không phải là một phần của ngôn ngữ C#. Nó là một phần của thư viện .net. –

+0

có thể trùng lặp của [StringBuilder quyết định dung lượng của nó như thế nào?] (Http://stackoverflow.com/questions/4495855/how-does-the-stringbuilder-decide-how-large-its-capacity-should -be) – bzlm

Trả lời

15

Phụ thuộc phiên bản .NET bạn đang nói đến. Trước .NET 4, StringBuilder sử dụng standard .NET strategy, tăng gấp đôi công suất của bộ đệm bên trong mỗi khi nó cần được mở rộng.

StringBuilder được viết lại hoàn toàn cho .NET 4, hiện đang sử dụng ropes. Mở rộng việc phân bổ bây giờ được thực hiện bằng cách thêm một đoạn dây khác lên tới 8000 ký tự. Không hoàn toàn hiệu quả như chiến lược trước đó nhưng tránh rắc rối với các bộ đệm lớn làm tắc nghẽn Heap đối tượng lớn. Mã nguồn có sẵn từ Nguồn tham khảo nếu bạn muốn xem xét kỹ hơn.

+0

Nó gây rối cho chúng tôi khi chúng tôi nâng cấp sản phẩm của mình từ .Net 3.5 lên .Net 4.5. Chúng tôi đã sử dụng đối tượng trình xây dựng chuỗi làm tham số cho cuộc gọi API gốc thông qua interop. Nó dẫn đến vấn đề tràn bộ đệm gây ra quá trình sụp đổ. Heap bộ nhớ đã bị hỏng khi API bản địa đã trở về chuỗi dài.Chúng tôi bắt đầu cung cấp năng lực rõ ràng trong constructor để bộ đệm có thể chăm sóc dây dài. Đáng ngạc nhiên nó cần phải được phá vỡ trước đó cũng cho chuỗi dài nhưng không bao giờ được báo cáo. thực hiện một số thủ thuật trong .Net 3.5 khi chúng ta sử dụng trình xây dựng chuỗi làm bộ đệm cho các API gốc? – RBT

+0

Điều đó làm hỏng heap GC trong cả hai phiên bản thời gian chạy. Tham nhũng như vậy không nhất thiết phải được phát hiện, bạn phải may mắn. Chắc chắn, bạn có xu hướng để có được may mắn hơn trong. NET 4 –

5

Chuẩn C# sẽ không chỉ định hành vi của một lớp thư viện BCL vì nó không liên quan gì đến đặc tả ngôn ngữ.

Theo như tôi biết, hành vi thực tế không được xác định trong bất kỳ đặc điểm kỹ thuật nào và thực hiện cụ thể.

AFAIK, Việc triển khai MS sẽ tăng gấp đôi dung lượng khi đạt được dung lượng hiện tại.

Xem thisthis câu hỏi SO trước đó.


Cập nhật:

này đã được thay đổi trong .NET 4.0. như được mô tả bởi Hans trong his answer. Bây giờ ropes được sử dụng, bổ sung thêm 8000 ký tự cùng một lúc.

MSDN, tuy nhiên là rất cẩn thận để chỉ ra rằng các hành vi thực tế là thực hiện cụ thể:

Các StringBuilder động phân bổ thêm không gian khi cần thiết và tăng công suất cho phù hợp. Vì lý do hiệu suất, một StringBuilder có thể cấp phát bộ nhớ nhiều hơn mức cần thiết. Lượng bộ nhớ được cấp phát cụ thể cho việc triển khai thực hiện.

+2

Chúng tôi không còn sử dụng chiến lược tăng gấp đôi khi toàn bộ. –

+1

@Eric - Cảm ơn bạn đã sửa tôi. Điều đó và câu trả lời từ Hans đã cho tôi biết thêm chi tiết. – Oded

-1

New StringBuilder (NET 4.5 hoặc cao hơn) phân bổ một bộ đệm nội m_ChunkChars theo yêu cầu của thông số công suất:

public StringBuilder(int capacity) { ... m_ChunkChars = new char[capacity]; ... }

Vì vậy, nếu công suất nhỏ hơn 40K chars nó đi vào Object nhỏ Heap. Tuy nhiên (trái với niềm tin phổ biến), StringBuilder sẽ vẫn phân bổ trên Heap đối tượng lớn nếu, sau đó, chúng tôi gọi sb.Append(...some string larger than 40K chars...); Có thể tìm thấy bản sửa lỗi có thể tìm thấy tại đây: https://github.com/amikunov/Large-Object-Heap-Fix-For-.NET-String-Builder

+1

Điều này không có gì ở tất cả để làm với những gì câu hỏi được yêu cầu. – Servy

Các vấn đề liên quan