2012-05-21 32 views
8

Trong một số mã máy chủ tcp không đồng bộ mà tôi có, đôi khi xảy ra lỗi khiến quá trình tiêu thụ toàn bộ bộ nhớ của hệ thống. Khi xem nhật ký, trình xem sự kiện và số MS docs vấn đề xảy ra nếu "ứng dụng gọi điện làm cho cuộc gọi IO không đồng bộ đến cùng một máy khách nhiều lần thì bạn có thể thấy phân mảnh heap và tăng byte riêng nếu ứng dụng khách từ xa dừng kết thúc I/O "dẫn đến việc tăng mức sử dụng bộ nhớ và ghim của các mảng cấu trúc và mảng byte System.Threading.OverlappedData.Cách tắt mã tcp không đồng bộ .NET sử dụng hết tài nguyên của hệ thống

Giải pháp đề xuất của bài viết KB là "đặt giới hạn trên cho số lượng bộ đệm nổi bật (gửi hoặc nhận) với IO không đồng bộ của chúng."

Làm cách nào để thực hiện việc này? Đây có phải là tham chiếu đến byte [] được gửi vào BeginRead không? Vì vậy, là giải pháp chỉ đơn giản là gói byte truy cập [] với một semaphore?

EDIT: Truy cập được kiểm soát bằng semaphore tới bộ đệm byte hoặc chỉ có bộ đệm byte có kích thước tĩnh là hai giải pháp phổ biến. Một vấn đề mà tôi vẫn còn tồn tại là khi vấn đề máy khách không đồng bộ này xảy ra (có thể đó là một sự kiện mạng lạ), có các semaphores hoặc các vùng đệm byte sẽ ngăn tôi thoát khỏi bộ nhớ, nhưng nó không giải quyết được vấn đề. Hồ bơi của tôi về bộ đệm sẽ có khả năng nhận được gobbled lên của khách hàng vấn đề (s), có hiệu lực khóa chức năng chính xác khách hàng hợp pháp ra ngoài.

CHỈNH SỬA 2: Đến đây tuyệt vời answer. Về cơ bản nó cho thấy làm thế nào để tự unpin đối tượng. Và trong khi mã TCP không đồng bộ rời khỏi các quy tắc thời gian chạy hậu trường, có thể ghi đè bằng cách ghim chặt chẽ từng bộ đệm trước khi sử dụng, sau đó bỏ ghim ở cuối khối hoặc cuối cùng. Tôi đang cố gắng tìm ra điều đó ngay bây giờ ...

+0

Có thể trùng lặp: http://stackoverflow.com/questions/236171/net-does-not-have-reliable-asynchronouos-socket-communication – Dennis

+0

Đó là về gói gọi đến BeginRead với semaphore. – mikalai

+0

Có lẽ đây là lý do chính đáng để cấu hình mã ... – gsscoder

Trả lời

3

Một cách để giải quyết vấn đề là bằng cách phân bổ trước bộ đệm và các cấu trúc dữ liệu khác được sử dụng trong giao tiếp không đồng bộ. Nếu bạn preallocate khi khởi động, sẽ không có phân mảnh, vì bộ nhớ sẽ tự nhiên cư trú trong cùng một khu vực của heap.

tôi khuyên bạn nên sử dụng ReceiveAsync/SendAsync API thêm vào NET 3.5 SP1, cho phép bạn cache hoặc tiền phân bổ cả SocketAsyncEventArgs cấu trúc và bộ đệm bộ nhớ lưu trữ trong SocketAsyncEventArgs.Buffer tài sản, không giống như cũ BeginXXX/EndXXX API mà chỉ cho phép bộ nhớ đệm hoặc phân bổ bộ nhớ đệm trước.

Sử dụng API cũ cũng phát sinh chi phí CPU đáng kể, bởi vì API trong nội bộ đã tạo Windows Overlapped I/O cấu trúc một lần nữa và một lần nữa. Trong API mới, điều này diễn ra trong phạm vi SocketAsyncEventArgs và do đó bằng cách gộp các đối tượng này, chi phí CPU chỉ được trả một lần.

Về cập nhật của bạn về ghim: ghim là có lý do, cụ thể là để ngăn GC di chuyển bộ đệm trong quá trình chống phân mảnh. Bằng cách bỏ thủ công, bạn có thể gây ra tham nhũng bộ nhớ.

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