Разумное количество потоков для пула потоков, выполняющего запросы к веб-сервису

Я знаю, что это связано со старым потоком. Но эта проблема все еще остается активной.

Я создал решение для своего собственного стека. Может быть полезным для других программистов.

Этот код проверяет, являются ли переменные неопределенными или нулевыми. В случае, если переменные не определены или имеют значение null, возвращается имя переменной. (С синтаксисом шаблона).

Это изменение проверено на underscorejs v1.6.0. С небольшими изменениями это будет работать до 1.9.1. Далее смотрим на Лодаш. Это будет работать с незначительными корректировками!

В сборке разработчика подчеркивания:

v1.6.0 правило: 1239

Правило более новых версий: 1575

Старый код:

if (escape) {
  source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
}
if (interpolate) {
  source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
}
if (evaluate) {
  source += "';\n" + evaluate + "\n__p+='";
}

Новый код:

if (escape) {
    source += "'+\n((typeof " + escape + " === \"undefined\" || " + escape + " === null) ? \"<%-" + (escape.toString()) + "%>\": _.escape(" + escape + "))+\n'";
}
if (interpolate) {
    source += "'+\n((typeof " + interpolate + " === \"undefined\" || " + interpolate + " === null) ? \"<%=" + (interpolate.toString()) +"%>\":" + interpolate + ")+\n'";
}
if (evaluate) {
    source += "';\n" + evaluate + "\n__p+='";
}
17
задан Raedwald 29 April 2014 в 15:48
поделиться

9 ответов

Если каждый рабочий поток должен выполнить вызов веб-службы, то на количество потоков в вашем пуле должно сильно влиять количество одновременных запросов, которое может обработать ваша веб-служба. Любое большее количество потоков не сделает ничего, кроме перегрузки веб-службы.

6
ответ дан 30 November 2019 в 13:40
поделиться

Я где-то читал, что оптимальное количество потоков - это количество ядер * 25. Похоже, что .NET использует это по умолчанию для ThreadPool. Однако, если у вас есть большое количество вызовов веб-службы, вам лучше использовать один поток и проверить список вызовов веб-службы на предмет ответа. Когда будет получен ответ, просто обработайте запись и удалите ее из списка.

2
ответ дан 30 November 2019 в 13:40
поделиться

Если каждое вычисление эквивалентно вызову веб-службы, то вы должны учитывать, какую нагрузку вы возлагаете на эту службу / сколько одновременных подключений эта служба выдержит или будет разрешена владельцы услуг. Большинство общедоступных сервисов ожидают только одно такое соединение от любого отдельного пользователя за раз. Если возможно, свяжитесь с владельцами сервисов, чтобы узнать их политику использования. Количество таких подключений будет определять количество потоков, которые вы можете использовать.

2
ответ дан 30 November 2019 в 13:40
поделиться

Если у вас есть доступ к сети для разработчиков рассмотрите возможность создания пакетной функции для проверки нескольких телефонных номеров за один вызов.

В более новой версии .NET есть ThreadPool, который может увеличиваться и уменьшаться в зависимости от своего собственного профиля производительности. К сожалению, версия Java либо фиксированная, либо увеличивается до предела в зависимости от поступающей работы.

Когда-то у нас были похожие проблемы. Наше решение заключалось в том, чтобы позволить заказчику регулировать размер пула и настраивать производительность по своему усмотрению.

При определении размера пула операций ввода-вывода могут учитываться некоторые свойства сети и данных:

2
ответ дан 30 November 2019 в 13:40
поделиться

Решение 1

Решение для первого набора ограничений состоит в том, чтобы в основном обернуть log4net.LogManager в свой собственный класс LogManager, например Jacob ], Джерун и Макваффлестикс предложили (см. Код ниже).

К сожалению, класс log4net.LogManager является статическим, а C # не поддерживает статическое наследование, поэтому вы не можете просто наследовать от него и переопределить метод GetLogger. Однако в классе log4net.LogManager методов не так уж много, так что это определенно возможно.

Другой недостаток этого решения заключается в том, что если у вас есть существующая база кода (что я делаю в в моем случае) вам придется заменить все существующие вызовы log4net.LogManager своим классом-оболочкой. Однако это не имеет большого значения для сегодняшних инструментов рефакторинга.

В моем проекте эти недостатки перевешивали преимущества использования конфигурации ведения журнала, предоставляемой вызывающим приложением, поэтому я выбрал Решение 2.

Код

Во-первых, вы нужен класс-оболочка LogManager:

using System;
using System.IO;
using log4net;
using log4net.Config;

namespace MyApplication.Logging
{
    //// TODO: Implement the additional GetLogger method signatures and log4net.LogManager methods that are not seen below.
    public static class LogManagerWrapper
    {
        private static readonly string LOG_CONFIG_FILE= @"path\to\log4net.config";

        public static ILog GetLogger(Type type)
        {
            // If no loggers have been created, load our own.
            if(LogManager.GetCurrentLoggers().Length == 0)
            {
                LoadConfig();
            }
            return LogManager.GetLogger(type);
        }

        private void LoadConfig()
        {
           //// TODO: Do exception handling for File access issues and supply sane defaults if it's unavailable.   
           XmlConfigurator.ConfigureAndWatch(new FileInfo(LOG_CONFIG_FILE));
        }              
}

Затем в ваших классах вместо:

private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

Используйте:

private static readonly ILog log = LogManagerWrapper.GetLogger(typeof(MyApp));

Решение 2

Для моих целей я решил остановиться на решении, которое соответствует второму набору ограничений. Смотрите код ниже для моего решения. Сборка может выбрать использование именованного репозитория журналирования, а не репозитория по умолчанию. Это полностью отделяет ведение журнала сборки от остальной части приложения. Это может быть очень полезно для разработчиков компонентов, которые хотят использовать log4net для своих компонентов, но не хотят требовать, чтобы все приложения, использующие их компонент, знали о log4net. Это также означает, что их конфигурация отладки отделена от конфигурации приложений. Сборка должна указывать RepositoryAttribute для установки своего репозитория журналов. "

Код

Я поместил следующие строки в файл AssemblyInfo.cs моей библиотеки классов:

 // Расположение файла конфигурации Log4Net Сборка может выбрать использование именованного репозитория журналирования, а не репозитория по умолчанию. Это полностью отделяет ведение журнала сборки от остальной части приложения. Это может быть очень полезно для разработчиков компонентов, которые хотят использовать log4net для своих компонентов, но не хотят требовать, чтобы все приложения, использующие их компонент, знали о log4net. Это также означает, что их конфигурация отладки отделена от конфигурации приложений. Сборка должна указывать RepositoryAttribute для установки своего репозитория журналов. "

Код

Я поместил следующие строки в файл AssemblyInfo.cs моей библиотеки классов:

 // Расположение файла конфигурации Log4Net Это может быть очень полезно для разработчиков компонентов, которые хотят использовать log4net для своих компонентов, но не хотят требовать, чтобы все приложения, использующие их компонент, знали о log4net. Это также означает, что их конфигурация отладки отделена от конфигурации приложений. Сборка должна указывать RepositoryAttribute для установки своего репозитория журналов. "

Код

Я поместил следующие строки в файл AssemblyInfo.cs моей библиотеки классов:

 // Расположение файла конфигурации Log4Net Это может быть очень полезно для разработчиков компонентов, которые хотят использовать log4net для своих компонентов, но не хотят требовать, чтобы все приложения, использующие их компонент, знали о log4net. Это также означает, что их конфигурация отладки отделена от конфигурации приложений. Сборка должна указывать RepositoryAttribute для установки своего репозитория журналов. "

Код

Я поместил следующие строки в файл AssemblyInfo.cs моей библиотеки классов:

 // Расположение файла конфигурации Log4Net
[сборка: log4net.Config.Repository ("CompanyName.IntegrationLibName")]
[сборка: log4net.Config.XmlConfigurator (ConfigFile = "CompanyName.IntegrationLibName.config", Watch = true)]

Ссылки

-121--2534050-

Не забывайте, что каждый поток, который вы создаете, также будет требовать памяти для размера своего стека. Таким образом, создание пула потоков повлияет на объем памяти вашего процесса (обратите внимание, что некоторые пулы не создают потоки до тех пор, пока они действительно не потребуются, поэтому при запуске вы не увидите увеличения памяти).

Этот стек размер настраивается с помощью -Xss (аналогично -Xmx и т. д.). Я считаю, что по умолчанию 512 КБ на поток. На данный момент я не могу найти никаких авторитетных подтверждений этого.

0
ответ дан 30 November 2019 в 13:40
поделиться

Предположим что веб-служба бесконечно масштабируема и никого не волнует, что вы засыпаете ее запросами. Предположим также, что ответы веб-службы находятся в диапазоне 1 секунда, а время локальной обработки составляет 5 миллисекунд.

Пропускная способность максимальна, когда у вас такое же количество занятых потоков, как и у процессорных ядер.

В этих предположениях вы не сможете максимизировать пропускную способность многоядерного процессора для любого разумного размера пула потоков. Чтобы достичь максимального количества транзакций в секунду, вы должны разбить поток на модель соединения. Ищите упомянутый ранее неблокирующий ввод-вывод (NIO) или реализацию Java шаблона токена асинхронного завершения (завершение ввода-вывода в Windows).

Обратите внимание, что стековая память, которая зарезервирована для каждого созданного потока, на самом деле является просто зарезервированным адресным пространством , а не фактически выделенной или выделенной памятью. Когда стек пытается вырасти, возникают исключения, что приводит к фиксации памяти стека по запросу. Как следствие, это актуально только для 32-битных менеджеров памяти. Для 64-разрядной памяти у вас есть огромное адресное пространство, даже если вы поддерживаете только небольшую часть этого пространства физической памятью. По крайней мере, я так понимаю, как работает Windows, но не уверен насчет мира Unix.

Обратите внимание, что стековая память, которая зарезервирована для каждого созданного потока, на самом деле является просто зарезервированным адресным пространством , а не фактически выделенной или выделенной памятью. Когда стек пытается вырасти, возникают исключения, что приводит к фиксации памяти стека по запросу. Как следствие, это актуально только для 32-битных менеджеров памяти. Для 64-разрядной памяти у вас есть огромное адресное пространство, даже если вы поддерживаете только небольшую часть этого пространства физической памятью. По крайней мере, я так понимаю, как работает Windows, но не уверен насчет мира Unix.

Обратите внимание, что стековая память, которая зарезервирована для каждого созданного потока, на самом деле является просто зарезервированным адресным пространством , а не фактически выделенной или выделенной памятью. Когда стек пытается вырасти, возникают исключения, что приводит к фиксации памяти стека по запросу. Как следствие, это актуально только для 32-битных менеджеров памяти. Для 64-разрядной памяти у вас есть огромное адресное пространство, даже если вы поддерживаете только небольшую часть этого пространства физической памятью. По крайней мере, я так понимаю, как работает Windows, но не уверен насчет мира Unix.

у вас огромное адресное пространство, даже если вы поддерживаете только небольшую часть этого пространства физической памятью. По крайней мере, я так понимаю, как работает Windows, но не уверен насчет мира Unix.

у вас огромное адресное пространство, даже если вы поддерживаете только небольшую часть этого пространства физической памятью. По крайней мере, я так понимаю, как работает Windows, но не уверен насчет мира Unix.

1
ответ дан 30 November 2019 в 13:40
поделиться

Интересно, не лучше ли вам использовать NIO, а не потоки, поскольку вашим ограничивающим фактором будет узкое место сервера + сети веб-службы, а не клиентского ЦП.

В противном случае, самое большее вы не должно превышать количество одновременных подключений, которое может поддерживать ваш веб-сервис.

0
ответ дан 30 November 2019 в 13:40
поделиться

Если вы выполняете тяжелые вычисления, скажем, для параллельных манипуляций с массивами, то практическое правило - количество потоков для количества процессоров.

0
ответ дан 30 November 2019 в 13:40
поделиться

Что-то, что можно было бы рассмотреть, - это рассмотрение

Runtime.getRuntime().availableProcessors()

, которое дает некоторое представление о том, сколько потоков имеет смысл для системы.

8
ответ дан 30 November 2019 в 13:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: