Ограничить использование процессора процессом - PullRequest
11 голосов
/ 02 июня 2010

У меня запущена служба, которая периодически проверяет папку на наличие файла и затем обрабатывает его. (Читает, извлекает данные, сохраняет их в sql)

Итак, я запустил его на тестовой коробке, и это заняло немного больше времени, чем ожидалось. Файл имел 1,6 миллиона строк, и он продолжал работать через 6 часов (потом я пошел домой).

Проблема в том, что окно, на котором он работает, теперь абсолютно повреждено - время ожидания удаленного рабочего стола истекло, поэтому я даже не могу его остановить, чтобы остановить процесс, или подключить отладчик, чтобы посмотреть, как далеко и т.д. Он полностью использует процессор + 90%, а все остальные работающие сервисы или приложения страдают.

Код (из памяти может не скомпилироваться):

List<ItemDTO> items = new List<ItemDTO>();
using (StreamReader sr = fileInfo.OpenText())
{
    while (!sr.EndOfFile)
    {
        string line = sr.ReadLine()
        try {
           string s = line.Substring(0,8);
           double y = Double.Parse(line.Substring(8,7));

           //If the item isnt already in the collection, add it.
           if (items.Find(delegate(ItemDTO i) { return (i.Item == s); }) == null)
               items.Add(new ItemDTO(s,y));
         }
         catch { /*Crash*/ }
    }
    return items;
}

- Поэтому я работаю над улучшением кода (приветствуются любые советы).

Но это все еще может быть медленным делом, и это нормально, у меня нет проблем с этим, если он не убивает мой сервер.

Итак, что я хочу от вас, прекрасные люди, это: 1) Мой код ужасно неоптимизирован? 2) Могу ли я ограничить количество процессора, которое может использовать мой блок кода?

Ура всем

Ответы [ 9 ]

10 голосов
/ 02 июня 2010

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

8 голосов
/ 02 июня 2010
  1. Выполнение поиска в списке является операцией O (n), это означает, что по мере того, как список становится длиннее, поиск элементов занимает больше времени. Вы можете поместить элементы в HashSet в .NET 4.0 / 3.5 или использовать Словарь для более ранних версий .NET, который может действовать как индекс, если вам нужны элементы в список, чтобы сохранить первоначальный порядок, вы можете продолжать помещать их в список, но используйте HashSet / Dictionary для выполнения проверок.

  2. Вы также можете запустить этот код в потоке BackgroundWorker , это поможет поддерживать отзывчивость интерфейса во время работы процесса.

4 голосов
/ 02 июня 2010

Найти в списке O (n). Если в файле 1,6 миллиона строк (т.е. 1,6 миллиона элементов), вы будете неоднократно просматривать список из более чем 1 миллиона строк, что будет тратить много времени.

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

Если вы используете .NET 3.5, вы можете использовать коллекцию HashSet, которая дает вам амортизированный O (1) для поиска. Или словарь коллекция использует .NET 2.0

Далее вы должны спросить себя, есть ли в файле 1,6 миллиона строк, достаточно ли памяти? Если вы это сделаете, то анализ файла в памяти будет быстрее, чем отправка его в базу данных для обработки дубликатов, но если у вас недостаточно памяти, вы будете пейджинговать. Много. (что, вероятно, сейчас и происходит).

3 голосов
/ 03 июня 2010

Как уже говорили другие, исправьте структуру данных.

Теперь, мои глаза попали на эту фразу "периодически проверяет папку на наличие файла и затем обрабатывает его". Как часто происходит «периодически» и почему обрабатывается файл, который, вероятно, не изменился?

Возможно, вы захотите взглянуть на System.IO.FileSystemWatcher http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx

1 голос
/ 02 июня 2010

В ответ на 1) я бы использовал отсортированный список (если имеется много избыточных данных) или хэш-словарь вместо обычного для ускорения поиска.

Вот другойпост , который поможет вам выбрать между двумя подходами.

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

1 голос
/ 02 июня 2010

вы не можете массово загрузить этот файл с SqlBulkCopy Class , а затем выполнить обработку на сервере базы данных?

0 голосов
/ 03 июня 2010

Я не программист на C #, но, глядя на логику, я думаю

  1. Вы создаете новый строковый объект каждый раз в цикле. Если я должен сделать это в Java, вместо использования строкового объекта, я бы использовал StringBuffer.

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

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

0 голосов
/ 03 июня 2010
  • HashSet
  • Потоки с более низким приоритетом
  • Какая-то массовая вставка SQL
0 голосов
/ 02 июня 2010

Вам действительно нужно хранить все данные в памяти? Вы можете сохранить его в базе данных (если вам нужно что-то простое и мощное, используйте Sqlite) и обработать его с помощью sql.

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