Повышение производительности многопоточных HttpWebRequests в .NET.
Я пытаюсь измерить пропускную способность веб-службы.
Для этого я написал небольшой инструмент, который непрерывно отправляет запросы и читает ответы от нескольких потоков.
Содержимое внутреннего цикла каждого потока выглядит следующим образом:
public void PerformRequest()
{
WebRequest webRequest = WebRequest.Create(_uri);
webRequest.ContentType = "application/ocsp-request";
webRequest.Method = "POST";
webRequest.Credentials = _credentials;
webRequest.ContentLength = _request.Length;
((HttpWebRequest)webRequest).KeepAlive = false;
using (Stream st = webRequest.GetRequestStream())
st.Write(_request, 0, _request.Length);
using (HttpWebResponse httpWebResponse = (HttpWebResponse)webRequest.GetResponse())
using (Stream responseStream = httpWebResponse.GetResponseStream())
using (BufferedStream bufferedStream = new BufferedStream(responseStream))
using (BinaryReader reader = new BinaryReader(bufferedStream))
{
if (httpWebResponse.StatusCode != HttpStatusCode.OK)
throw new WebException("Got response status code: " + httpWebResponse.StatusCode);
byte[] response = reader.ReadBytes((int)httpWebResponse.ContentLength);
httpWebResponse.Close();
}
}
Кажется, что все в порядке, за исключением того, что что-то, кажется, ограничивает инструмент. Если я запускаю два экземпляра инструмента с каждым 40 потоками, я получаю значительно большую пропускную способность, чем один экземпляр с 80 потоками.
Я нашел свойство ServicePointManager.DefaultConnectionLimit, которое я установил для 10000 (и это не имеет значения, если я установил его через app.config как было предложено Jader Dias).
Есть ли другие настройки в .NET или на моей машине, которые могут влиять на производительность? (Я запускаю Vista, но я вижу ту же проблему в Windows Server 2003).
Возможно, некоторые ограничения на количество соединений, которые может сделать один процесс?
Ответы
Ответ 1
Вы должны установить параметр maxconnection в файле app.config или web.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<connectionManagement>
<add address="*" maxconnection="80"/>
</connectionManagement>
</system.net>
</configuration>
Значения до 100 отлично работают с Windows XP.
Обновление: Я только узнал, что приведенный выше метод является альтернативным способом установки System.Net.ServicePointManager.DefaultConnectionLimit
Ответ 2
это может быть ограничение связи, которое было введено недавно.
http://www.speedguide.net/read_articles.php?id=1497
и
http://www.mydigitallife.info/2007/04/09/windows-vista-tcpipsys-connection-limit-patch-for-event-id-4226/
Ответ 3
Вы пытались увеличить максимальные соединения в сетевых настройках?
http://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx
Ответ 4
Помните, что многопоточный код всегда может вызывать конфликты на любых общих ресурсах, и даже если вы явно не разделяете что-либо, вы можете использовать классы, которые совместно используют ресурсы под обложками.
Если вы действительно получаете лучшую производительность с помощью 2 40 потоков exes, чем 1 80 thread exe, вам нужно начать расследование с помощью общих ресурсов. И если это так, код, который вы указали, гораздо менее интересен, чем код, который создает и управляет потоками.
Другая вещь, которую я бы выбрал, есть несколько инструментов, которые вы можете получить, которые будут делать это для вас в целом. См. http://support.microsoft.com/kb/231282. Также включен в Visual Studio (я не уверен, что skus) - это новое поколение инструментов тестирования производительности веб-приложений. И я уверен, что если бы вы посмотрели, вы могли бы найти не-MS-материал тоже.
Ответ 5
Существует два важных аспекта производительности w.r.t:
-
Один из аспектов, предложенный всеми, количество TCP-соединений используется клиентом
(обычно лучше, если эти соединения сохраняются (keep alive = true)), для получения подробной информации обратитесь к: http://msdn.microsoft.com/en-us/library/system.net.servicepoint.connectionlimit(v=vs.110).aspx, Как и где TCP-соединение было создано в httpwebrequest и как оно связано с точкой обслуживания?, Почему System.Net.ServicePoint.ConnectionLimit использует "7FFFFFFF '(Int32.MaxValue/2147483647), когда клиент подключается к службе на" localhost "?, System.Net.ServicePointManager.DefaultConnectionLimit и .MaxServicePointIdleTime)
-
Второй аспект - это не использование нескольких новых потоков/или использование рабочих потоков для параллельной работы с использованием синхронных вызовов (например, httpwebrequest.getrequeststream) в фрагменте кода, полностью охватывающих полностью асинхронную модель (например, begin/endrequeststream или новые варианты задач). Таким образом, процессор будет всегда занят и поток потоков завершения ввода-вывода просто отправит ответ в потоке рабочего потока (потока пулов), вызвав обратный вызов. (вы можете ссылаться на: Как .NET использует потоки ввода-вывода или порты завершения ввода-вывода?, http://blog.marcgravell.com/2009/02/async-without-pain.html, HttpWebRequest и порты завершения ввода-вывода)
С уважением.
Ответ 6
Как вы создаете свои темы? Я предполагаю, что, поскольку вы знаете, что у вас есть 80 потоков, вы не используете диспетчер threadpool, потому что с помощью диспетчера threadpool вы можете запрашивать столько потоков, сколько хотите, и вы получите только 25 активных потоков за раз. Если вы создаете потоки вручную с помощью массива, то вы фактически получите столько, сколько вам нужно, однако они все еще находятся в одном и том же пространстве процессов, что может ограничить их потоками, запущенными в отдельных процессах.
Вы также можете посмотреть, в каком стиле квартиры создаются потоки, я считаю, что класс Thread ctor использует STA по умолчанию. Попробуйте MTA и посмотрите, влияют ли они на производительность.