Tôi không có tất cả các câu trả lời. Hy vọng rằng tôi có thể đổ một số ánh sáng trên đó.
Để đơn giản hóa các tuyên bố trước đây của tôi về các mô hình luồng của .NET, chỉ cần biết rằng Thư viện song song sử dụng Tác vụ và Trình quản lý tác vụ mặc định cho Tác vụ, sử dụng ThreadPool. Bạn càng lên cao trong hệ thống phân cấp (ThreadPool ở dưới cùng), bạn càng có nhiều chi phí khi tạo các mục. Chi phí hoạt động thêm đó chắc chắn không có nghĩa là nó chậm hơn, nhưng thật tốt khi biết rằng nó ở đó. Cuối cùng, hiệu suất của thuật toán của bạn trong một môi trường đa luồng đi xuống thiết kế của nó. Những gì thực hiện tốt tuần tự có thể không thực hiện tốt song song. Có quá nhiều yếu tố liên quan để cung cấp cho bạn các quy tắc cứng và nhanh, chúng thay đổi tùy thuộc vào những gì bạn đang cố gắng thực hiện. Vì bạn đang xử lý các yêu cầu mạng, tôi sẽ thử và đưa ra một ví dụ nhỏ.
Hãy để tôi nói rằng tôi không phải là chuyên gia về ổ cắm, và tôi không biết gì về Zeroc-Ice. Tôi biết về bit về các hoạt động không đồng bộ, và đây là nơi nó sẽ thực sự giúp bạn. Nếu bạn gửi yêu cầu đồng bộ qua ổ cắm, khi bạn gọi Socket.Receive()
, chuỗi của bạn sẽ chặn cho đến khi nhận được yêu cầu. Điều này không tốt. Chủ đề của bạn không thể thực hiện thêm bất kỳ yêu cầu nào kể từ khi nó bị chặn. Sử dụng Socket.Beginxxxxxx (), yêu cầu I / O sẽ được thực hiện và đưa vào hàng đợi IRP cho ổ cắm và luồng của bạn sẽ tiếp tục. Điều này có nghĩa là, chủ đề của bạn thực sự có thể thực hiện hàng ngàn yêu cầu trong một vòng lặp mà không có bất kỳ chặn nào cả!
Nếu tôi hiểu bạn chính xác, bạn đang sử dụng các cuộc gọi qua Zeroc-Ice trong mã thử nghiệm của mình, không thực sự cố gắng đạt đến điểm cuối http. Nếu đó là trường hợp, tôi có thể thừa nhận rằng tôi không biết Zeroc-Ice hoạt động như thế nào. Tuy nhiên, tôi sẽ đề nghị làm theo lời khuyên được liệt kê ở đây , đặc biệt là phần : Consider Asynchronous Method Invocation (AMI)
. Trang này hiển thị điều này:
Bằng cách sử dụng AMI, máy khách sẽ lấy lại chuỗi điều khiển ngay khi lệnh được gửi (hoặc, nếu không thể gửi ngay lập tức, đã được xếp hàng), cho phép máy khách sử dụng luồng đó để thực hiện công việc hữu ích khác trong thời gian trung bình .
Có vẻ như tương đương với những gì tôi đã mô tả ở trên bằng cách sử dụng ổ cắm .NET. Có thể có những cách khác để cải thiện hiệu suất khi cố gắng thực hiện nhiều lần gửi, nhưng tôi sẽ bắt đầu ở đây hoặc với bất kỳ đề xuất nào khác được liệt kê trên trang đó. Bạn đã rất mơ hồ về thiết kế ứng dụng của bạn, vì vậy tôi có thể cụ thể hơn tôi đã ở trên. Chỉ cần nhớ, không sử dụng nhiều luồng hơn mức cần thiết để có được những gì bạn cần, nếu không bạn sẽ thấy ứng dụng của mình chạy chậm hơn bạn muốn.
Một số ví dụ trong mã giả (đã cố gắng làm cho nó càng gần băng càng tốt mà tôi không thực sự phải học nó):
var iterations = 100000;
for (int i = 0; i < iterations; i++)
{
// The thread blocks here waiting for the response.
// That slows down your loop and you're just wasting
// CPU cycles that could instead be sending/receiving more objects
MyObjectPrx obj = iceComm.stringToProxy("whateverissupposedtogohere");
obj.DoStuff();
}
Một cách tốt hơn:
public interface MyObjectPrx : Ice.ObjectPrx
{
Ice.AsyncResult GetObject(int obj, Ice.AsyncCallback cb, object cookie);
// other functions
}
public static void Finished(Ice.AsyncResult result)
{
MyObjectPrx obj = (MyObjectPrx)result.GetProxy();
obj.DoStuff();
}
static void Main(string[] args)
{
// threaded code...
var iterations = 100000;
for (int i = 0; i < iterations; i++)
{
int num = //whatever
MyObjectPrx prx = //whatever
Ice.AsyncCallback cb = new Ice.AsyncCallback(Finished);
// This function immediately gets called, and the loop continues
// it doesn't wait for a response, it just continually sends out socket
// requests as fast as your CPU can handle them. The response from the
// server will be handled in the callback function when the request
// completes. Hopefully you can see how this is much faster when
// sending sockets. If your server does not use an Async model
// like this, however, it's quite possible that your server won't
// be able to handle the requests
prx.GetObject(num, cb, null);
}
}
Hãy nhớ rằng nhiều chủ đề hơn! = Hiệu suất tốt hơn khi cố gắng gửi ổ cắm (hoặc thực sự làm bất cứ điều gì). Chủ đề không phải là phép thuật ở chỗ chúng sẽ tự động giải quyết bất kỳ vấn đề nào bạn đang làm việc. Lý tưởng nhất là bạn muốn có 1 luồng trên mỗi lõi, trừ khi một luồng dành nhiều thời gian chờ đợi, thì bạn có thể biện minh là có nhiều hơn. Chạy mỗi yêu cầu trong luồng riêng của nó là một ý tưởng tồi, vì các chuyển đổi ngữ cảnh sẽ xảy ra và lãng phí tài nguyên. (Nếu bạn muốn xem mọi thứ tôi đã viết về điều đó, hãy nhấp vào chỉnh sửa và xem các bản sửa đổi trước đây của bài đăng này. Tôi đã xóa nó vì nó dường như chỉ che mờ vấn đề chính trong tay.)
Bạn chắc chắn có thể thực hiện các yêu cầu này trong các luồng, nếu bạn muốn thực hiện một số lượng lớn yêu cầu mỗi giây. Tuy nhiên, đừng quá nhiệt tình với việc tạo chủ đề. Tìm một sự cân bằng và gắn bó với nó. Bạn sẽ có hiệu suất tốt hơn nếu bạn sử dụng mô hình không đồng bộ so với mô hình đồng bộ.
Tôi hy vọng điều đó sẽ giúp.