2010-08-02 53 views
11

Đây có phải là:Sẽ khai báo một biến bên trong/bên ngoài một vòng lặp thay đổi hiệu suất?

foreach(Type item in myCollection) 
{ 
    StringBuilder sb = new StringBuilder(); 
} 

chậm hơn nhiều so với:

StringBuilder sb = new StringBuilder(); 

foreach(Type item in myCollection) 
{ 
    sb = new StringBuilder(); 
} 

Nói cách khác, nó sẽ thực sự có vấn đề mà tôi tuyên bố StringBuilder của tôi?

+3

Tương tự như http://stackoverflow.com/questions/2447475/best-practice-for-creating-objects-used-in-for-foreach-loops –

+1

Lỗi không liên quan là phiên bản thứ hai nên được khởi tạo thành null để tránh phân bổ quá mức. –

Trả lời

12

Bạn có thể có thể đạt được một số hiệu suất, nếu bạn viết này:

StringBuilder sb = new StringBuilder(); 
foreach(Type item in myCollection) 
{ 
    sb.Length = 0; 
} 

Vì vậy, bạn phải nhanh chóng StringBuilder chỉ một lần và thiết lập lại kích thước trong vòng lặp, mà nên hơi nhanh hơn so với instantiating một đối tượng mới .

+0

+1 điểm tốt ... – SLaks

+1

+1: tùy thuộc vào kích thước của chuỗi được tạo và bộ đệm bên trong kết quả trong sb, điều này có thể tạo ra sự khác biệt có thể đo lường được. – Alex

+2

Nó có thể, nhưng nó cũng có thể không. Khi bạn gọi 'ToString', nó sẽ sao chép bộ đệm. Tôi muốn chuẩn bị nó, giả sử có bất kỳ lý do gì để nghĩ rằng nó có hiệu suất nhạy cảm. –

14

Không, nó sẽ không quan trọng về hiệu suất khi bạn khai báo nó.

Để có độ sạch mã chung, bạn nên khai báo nó trong phạm vi bên trong nhất mà nó được sử dụng - ví dụ: ví dụ đầu tiên của bạn.

+1

Điều này nên biên dịch vào cùng một IL anyway tôi nghĩ.Vâng, nó sẽ nếu anh ta không khởi tạo sb hai lần. –

+1

Sửa tôi nếu tôi sai, nhưng nếu bạn khai báo nó bên trong vòng lặp thì điều đó sẽ không làm cho nó không sử dụng được bên ngoài nó (không khai báo)? – NullUserException

+3

@NullUserException Có, bạn đã đúng. Nhưng nếu bạn không cần nó bên ngoài vòng lặp, nó là rõ ràng hơn để tuyên bố nó bên trong vòng lặp – sloth

2

Trong ví dụ thứ hai, bạn đang tạo thêm một thể hiện của StringBuilder. Ngoài ra, cả hai đều giống nhau, do đó, vấn đề hiệu suất là không thể bỏ qua.

+0

Điều này nên là một bình luận cho câu hỏi theo ý kiến ​​của tôi. – Shaihi

+0

@Shaihi - Tại sao? w69rdy đang đưa ra câu trả lời cho câu hỏi. – mphair

1

Không có đủ mã ở đây để chỉ rõ sự khác biệt về hiệu suất trong trường hợp cụ thể của bạn. Có nói rằng, sự khác biệt giữa việc khai báo một biến tham chiếu bên trong một vòng lặp như thế này so với bên ngoài là tầm thường đối với hầu hết các trường hợp.

1

Sự khác biệt hiệu quả giữa hai mẫu mã của bạn là thứ hai sẽ phân bổ thêm 1 bản sao của StringBuilder so với lần đầu tiên. Tác động hiệu suất của điều này so với phần còn lại của ứng dụng của bạn về bản chất là không có gì.

0

Cách tốt nhất để kiểm tra là thử cả hai phương pháp trong một vòng lặp, khoảng 100.000 mỗi lần. Đo thời lượng mỗi 100.000 lần lặp lại và so sánh chúng. Tôi không nghĩ có nhiều sự khác biệt. Nhưng có một sự khác biệt nhỏ, mặc dù. Ví dụ đầu tiên sẽ có nhiều biến số như số lần lặp. Ví dụ thứ hai chỉ có một biến. Trình biên dịch đủ thông minh để thực hiện một số tối ưu hóa ở đây, vì vậy bạn sẽ không nhận thấy một sự cải thiện tốc độ. Tuy nhiên, nếu bạn không muốn sử dụng đối tượng cuối cùng được tạo bên trong vòng lặp khi bạn ở bên ngoài vòng lặp, thì giải pháp đầu tiên sẽ tốt hơn. Trong giải pháp thứ hai, nó chỉ mất một lúc trước khi bộ thu gom rác sẽ giải phóng đối tượng cuối cùng được tạo ra. Trong ví dụ đầu tiên, bộ thu gom rác sẽ nhanh hơn một chút trong việc giải phóng đối tượng. Nó phụ thuộc vào phần còn lại của mã nhưng nếu bạn lưu trữ rất nhiều dữ liệu trong đối tượng StringBuilder này thì ví dụ thứ hai có thể giữ cho bộ nhớ này lâu hơn rất nhiều, do đó làm giảm hiệu suất mã của bạn sau khi rời khỏi vòng lặp!
Sau đó, một lần nữa, nếu các đối tượng ăn lên 100 KB và bạn có 16 GB trong máy của bạn, không ai quan tâm ... Bộ thu gom rác cuối cùng sẽ giải phóng nó một lần nữa, có thể ngay khi bạn rời khỏi phương thức chứa vòng lặp này.

0

Nếu bạn có các phân đoạn mã loại tương tự khác, bạn luôn có thể cấu hình hoặc đặt một số bộ định thời xung quanh mã và chạy thử nghiệm loại điểm chuẩn để tự mình xem. Một yếu tố khác sẽ là dấu chân bộ nhớ, mà những người khác đã nhận xét.

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