У мене немає всіх відповідей. Сподіваюся, я можу пролити трохи світла на це.
Для спрощення моїх попередніх тверджень про вбудовані моделі .NET, просто знайте, що бібліотека Parallel використовує завдання, а програму TaskScheduler за завданнями використовує ThreadPool. Чим вище ви йдете в ієрархії (ThreadPool знаходиться внизу), тим більше накладних витрат при створенні елементів. Цей додатковий наклад, звичайно, не означає, що він повільніше, але добре знати, що він є. Зрештою, ефективність вашого алгоритму в багатопотоковому середовищі зводиться до його дизайну. Те, що працює добре послідовно, може не працювати так само паралельно. Занадто багато факторів, щоб дати вам жорсткі та швидкі правила, вони змінюються залежно від того, що ви намагаєтесь зробити. Оскільки ви маєте справу з мережевими запитами, я спробую навести невеликий приклад.
Дозвольте констатувати, що я не знавець у розетках, і майже нічого не знаю про Zeroc-Ice. Я знаю про біт про асинхронні операції, і саме це вам справді допоможе. Якщо ви надсилаєте синхронний запит через сокет, під час дзвінка Socket.Receive()
ваша нитка блокується до отримання запиту. Це не добре. Ваш потік більше не може надсилати запити, оскільки він заблокований. Використовуючи Socket.Beginxxxxxx (), запит вводу / виводу буде зроблений і поміщений у чергу IRP для сокета, і ваша нитка продовжуватиме працювати. Це означає, що ваш потік насправді може робити тисячі запитів у циклі, не блокуючи його взагалі!
Якщо я вас правильно зрозумів, ви використовуєте дзвінки через Zeroc-Ice у своєму тестовому коді, насправді не намагаєтесь досягти кінцевої точки http. Якщо це так, я можу визнати, що я не знаю, як працює Zeroc-Ice. Я б, однак, запропонувати після консультацій , перерахованих тут , в зокрема , частина: Consider Asynchronous Method Invocation (AMI)
. На сторінці показано це:
Використовуючи AMI, клієнт повертає нитку управління, як тільки надіслане виклик (або, якщо його неможливо відправити негайно, у черзі), що дозволяє клієнту використовувати цей потік для виконання іншої корисної роботи в середній час .
Що здається еквівалентом тому, що я описав вище, використовуючи розетки .NET. Можливо, існують інші способи покращити ефективність, коли намагаються зробити багато надсилань, але я б почав тут або з будь-якої іншої пропозиції, переліченої на цій сторінці. Ви дуже розпливчали дизайн своєї заявки, тому я можу бути більш конкретним, ніж я був вище. Пам'ятайте, не використовуйте більше потоків, ніж це абсолютно необхідно, щоб зробити те, що вам потрібно, інакше, швидше за все, ваша програма працює набагато повільніше, ніж вам потрібно.
Деякі приклади в псевдокоді (намагався зробити це максимально наближеним до льоду, не маючи насправді цього вивчати):
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();
}
Кращий спосіб:
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);
}
}
Майте на увазі, що більше тем! = Краща продуктивність при спробі надсилання сокетів (або дійсно що-небудь робити). Нитки не є магією, оскільки вони автоматично вирішать будь-яку проблему, над якою ви працюєте. В ідеалі вам потрібно 1 нитка на ядро, якщо нитка не витрачає багато часу на очікування, то ви можете виправдати наявність більше. Запуск кожного запиту у власному потоці - погана ідея, оскільки відбуватимуться переключення контексту та витрачання ресурсів. (Якщо ви хочете побачити все, що я написав про це, натисніть редагувати і подивіться на минулі редакції цієї публікації. Я видалив її, оскільки вона, здавалося, затуманила основну проблему.)
Ви точно можете зробити цей запит у нитках, якщо ви хочете робити велику кількість запитів за секунду. Однак не перестарайтеся створювати нитки. Знайдіть рівновагу і дотримуйтесь її. Ви отримаєте кращі показники, якщо будете використовувати асинхронну модель проти синхронної.
Я сподіваюся, що це допомагає.