У меня нет всех ответов. Надеюсь , я могу пролить некоторый свет на это.
Чтобы упростить мои предыдущие утверждения о моделях потоков .NET, просто знайте, что Parallel Library использует Tasks, а TaskScheduler по умолчанию для Tasks использует 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 поток на ядро, если поток не тратит много времени на ожидание, тогда вы можете оправдать наличие большего. Выполнение каждого запроса в своем собственном потоке - плохая идея, поскольку произойдет переключение контекста и потеря ресурсов. (Если вы хотите увидеть все, что я написал об этом, нажмите «Изменить» и посмотрите последние редакции этого поста. Я удалил его, поскольку казалось, что он лишь затуманивает основную проблему.)
Вы можете определенно сделать эти запросы в потоках, если вы хотите делать большое количество запросов в секунду. Однако, не переусердствуйте с созданием потока. Найдите баланс и придерживайтесь его. Вы получите лучшую производительность, если будете использовать асинхронную модель по сравнению с синхронной.
Надеюсь, это поможет.