2011-11-07 31 views
7

Tôi đang viết một ứng dụng .NET quan trọng về hiệu suất, sử dụng nhiều luồng đa luồng.Lập hồ sơ/tối ưu hóa ứng dụng đa luồng nhiều ứng dụng

Sử dụng Visual hiệu suất Studio hồ sơ, các bộ phận chức năng với mẫu độc quyền là:

WaitHandle.WaitAny() - 14,23%

@[email protected]-7,76%

Monitor.Enter-5,09%

Về cơ bản, tôi 3 chức năng hàng đầu đang làm việc với các luồng nguyên thủy và ngoài tầm kiểm soát của tôi ở một mức độ nào đó mà tôi tin. Công việc/quy trình xử lý của tôi khá nhỏ so với tôi và tôi đang cố gắng tăng hiệu suất. Tôi tin rằng các thuật toán liên quan là khá âm thanh, mặc dù tôi đang xem xét chúng khá thường xuyên.

Câu hỏi của tôi là:

  • Nếu có 14,23% số mẫu CPU trong những phương pháp - là CPU có hiệu quả 'nhàn rỗi' đối với hầu hết những người mẫu, nghĩa là chỉ chờ đợi vào chủ đề khác? Hoặc là phần nhàn rỗi của chuỗi chờ đợi không được hiển thị như một phần của dấu vết hồ sơ [và 27,08% được hiển thị trong 3 tổng của tất cả chi phí này trong các phương thức đồng bộ đó]? (Tôi có thể đoán rằng điều này chủ yếu là nhàn rỗi, nhưng sẽ đánh giá cao một số tài liệu tham khảo phong nha đằng sau câu trả lời cho điều này xin vui lòng)
  • Tôi đã xem xét các sơ đồ khóa của mình, tuy nhiên những kết quả này cho thấy một số nút cổ chai cụ thể hoặc kỹ thuật tôi nên xem xét thêm tối ưu hóa?
  • Có phải là WaitAny khá kém đặc biệt không? Tôi sử dụng nó rất nhiều để kiểm tra xem các đối tượng hàng đợi cụ thể có thể đọc được/ghi được hay không, nhưng cũng kiểm tra cờ hủy bỏ cùng một lúc. Có cách nào tốt hơn để làm điều đó không?
+0

Nó có thể là cách bạn _use_ những nguyên thủy đó. –

+0

@Henk - thực sự, tôi đã cố gắng ám chỉ điều đó bằng cách nói trong việc xem lại các thuật toán của tôi, khóa sơ đồ –

+0

@KierenJohnstone Nếu bạn có VS 2010, có lẽ tốt hơn nên sử dụng Concurrency Profiler/Visualizer cho việc này. –

Trả lời

4

CPU của bạn không nhất thiết phải không hoạt động khi có chỉ trong một số WaitHandle.WaitAny hoặc Monitor.Enter. Một chủ đề đang chờ trong khi chờ, nhưng có lẽ các chủ đề khác đang bận thi hành. Điều này đặc biệt đúng với Monitor.Enter. Nếu một sợi bị khóa trên một khóa, thì một người sẽ hy vọng luồng có khóa đó đang thực thi mã thay vì đang ngồi nhàn rỗi.

Ngoài ra, nếu chuỗi của bạn đang sử dụng WaitAny để đọc từ hàng đợi, thì có khả năng hàng đợi đơn giản là không có bất kỳ thứ gì trong đó. Đó không phải là vấn đề hiệu suất đối với mã người tiêu dùng. Nó chỉ có nghĩa là nhà sản xuất không đưa mọi thứ vào hàng đợi đủ nhanh. Điều này có thể là do nhà sản xuất chậm hoặc vì dữ liệu không đủ nhanh.

Nếu bạn đang xử lý dữ liệu nhanh hơn mức có thể xuất hiện, thì có vẻ như bạn không gặp vấn đề về hiệu suất. Chắc chắn không phải ở phía người tiêu dùng.

Theo như sử dụng WaitAny để xếp hàng, tôi khuyên bạn nên sử dụng BlockingCollection và các phương pháp lấy mã thông báo hủy, như TryAdd(T, Int32, CancellationToken). Việc chuyển đổi sang mã thông báo hủy thực sự đơn giản hóa mã xếp hàng đa luồng của tôi.

+0

Cảm ơn tôi sẽ kiểm tra bộ sưu tập đó. Về mặt sử dụng CPU tổng thể, tôi biết khi nào một luồng đang đợi những thứ khác có thể bận, bất kỳ ý tưởng nào nếu các mẫu được chụp ở đó đều được tính là luồng mà chúng được chụp ở chế độ chờ hoặc là các mẫu được ghi. 'đang chờ đợi'? –

+0

Ngoài ra, tôi cũng đang sản xuất cũng như tiêu thụ. Mã sản xuất được bao gồm trong theo dõi hồ sơ này. Tôi sau đó sẽ mong đợi để xem mã sản xuất gần đầu sau đó - ??? –

+0

@Kieren: Nếu một mẫu hiển thị một chuỗi không hoạt động (trong 'WaitAny' hoặc' Monitor.Enter'), thì tôi mong rằng nó sẽ không hoạt động. Người ta sẽ mong đợi rằng bất kỳ chi phí hồ sơ sẽ được loại bỏ khỏi số liệu thống kê. Theo như những gì bạn mong đợi để xem, tôi không biết đủ về ứng dụng của bạn để nói. Nhà sản xuất cũng có thể không hoạt động nếu đang chờ dữ liệu từ luồng mạng hoặc tệp đĩa hoặc nội dung nào đó. –

4

Thống kê lược tả không bao gồm thời gian các chủ đề bị chặn.

Trình thu thập dựa trên lấy mẫu về cơ bản yêu cầu mỗi lõi báo cáo lại sau mỗi chu kỳ không sử dụng X (nói 1.000.000).Mỗi khi một lõi báo cáo trở lại, trình lược tả ghi nhớ ngăn xếp cuộc gọi hiện tại. Các kết quả lược tả được xây dựng lại từ các ngăn xếp cuộc gọi mà profiler ghi lại.

Từ kết quả lược tả, bạn biết rằng 14,23% thời gian một lõi đang làm việc, nó đang thực hiện các hướng dẫn trong WaitHandle.WaitAny. Nếu chương trình của bạn bị ràng buộc CPU, tối ưu hóa phần WaitAny (ví dụ: sử dụng nguyên thủy khác) có thể có tác động đáng kể đến hiệu suất. Tuy nhiên, nếu chương trình là không phải CPU bị ràng buộc và dành phần lớn thời gian chờ đợi trên máy chủ, đĩa, quá trình khác hoặc một số đầu vào bên ngoài khác, thì tối ưu hóa mã liên quan đến WaitAny sẽ không hữu ích lắm.

Vì vậy, bước tiếp theo của bạn nên tìm hiểu cách sử dụng CPU của chương trình của bạn là gì. Ngoài ra, lưu ý Trình hiển thị đồng thời mà Ilian đề cập có thể hữu ích để hiểu cách các chủ đề trong chương trình của bạn dành thời gian của chúng.

+0

Chương trình như một toàn bộ sử dụng ~ 70% CPU, tôi sẽ xem xét các lựa chọn WaitAny như BlockingCollection Jim nói về. –

+0

Hey Kieren, mọi thông tin cập nhật về cái này? làm thế nào bạn đã cải thiện tiêu thụ CPU của bạn cuối cùng? –

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