Я правильно использую ThreadPool и производительность - PullRequest
1 голос
/ 16 декабря 2009

У меня есть служба Windows .net, которая работает через очередь элементов и проводит некоторые исследования по каждому из них. Я пытаюсь изменить его на многопоточную модель, чтобы можно было одновременно исследовать партии элементов, а не последовательно выполнять каждый элемент.

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

  1. В приведенном ниже примере у меня есть правильное представление об этом, когда дело доходит до потоков?
  2. По общему признанию, я запускаю это на ВМ, так что это может ухудшить производительность, однако я ожидал немного большего улучшения скорости. В настоящее время я наблюдаю улучшение примерно на 10% и надеялся, что при исследовании 5 или более рядом это будет намного быстрее, чем это (то есть, предпочтительно в 1/5 раза, но, конечно, я должен ожидать, по крайней мере, 50%?). Помимо ограничения на ожидание самого медленного предмета, чтобы закончить исследование, я ограничил это тем, как я сделал блокировку или что-то еще?

    static object locker = new Object();
    private List<string> currentItems = new List<string>();
    
    private void researcherTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if(Monitor.TryEnter(locker))
        {
            try
            {
                if (currentItems.Count == 0)
                {
                    // get the next x items from the db and adds them to the currentItems list
                    SetNextItems(); 
                    if (currentItems.Count > 0)
                    {
                        foreach (string item in currentItems)
                        {
                            ThreadPool.QueueUserWorkItem(ResearchInThread, item);
                        }
                    }
                }
            }
            finally
            {
                Monitor.Exit(locker);
            }
        }
    }
    
    void ResearchInThread(object item)
    {
        string currentItem = (string)item;
        try
        {
            // Research Process Here
        }
        finally
        {
            // Remove this item from the current list
            lock (locker)
            {
                currentItems.Remove(currentItem);
            }
        }
    }
    

Ответы [ 3 ]

2 голосов
/ 16 декабря 2009

Увеличение производительности во многом зависит от вашего оборудования (у вас есть многоядерный?) И от алгоритма, который вы выполняете параллельно.

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

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

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

Что касается вашего кода , я бы порекомендовал вам создать одну большую очередь «заданий» (ваш item объект), а затем создать определенное количество потоков, которые извлекают задания из эта очередь пока не пусто. Потоки будут работать, пока они не увидят, что очередь пуста. Таким образом, вам не придется ждать самого медленного работника, прежде чем выпускать следующую партию. Это должно помочь с общим увеличением производительности.

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

0 голосов
/ 16 декабря 2009

Вы пропустили основную часть кода. Как функция таймера вызывается «researchcherTimer_Elapsed».

При каких условиях время истекает.

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

0 голосов
/ 16 декабря 2009

Возможное повышение производительности может заключаться в использовании делегата System.Threading.Timer и TimerCallback вместо System.Timer, на который может влиять производительность системы, т. Е. Если система Занято, таймер не всегда срабатывает вовремя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...