Ограничьте использование ЦП процесса

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

Таким образом, я выполнил его на тестовом поле, и это взяло немного дольше thaan ожидаемый. Файл имел 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) Банка, я ограничиваю сумму ЦП, который может использовать мой блок кода?

Аплодисменты все

11
задан jb. 2 June 2010 в 18:54
поделиться

9 ответов

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

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

8
ответ дан 3 December 2019 в 03:34
поделиться

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

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

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

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

4
ответ дан 3 December 2019 в 03:34
поделиться

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

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

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

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

0
ответ дан 3 December 2019 в 03:34
поделиться

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

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

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

1
ответ дан 3 December 2019 в 03:34
поделиться
  • Hashset
  • Потоки с более низким приоритетом
  • Какая-то массовая вставка SQL
0
ответ дан 3 December 2019 в 03:34
поделиться

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

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

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

3
ответ дан 3 December 2019 в 03:34
поделиться

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

10
ответ дан 3 December 2019 в 03:34
поделиться

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

1
ответ дан 3 December 2019 в 03:34
поделиться

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

0
ответ дан 3 December 2019 в 03:34
поделиться
Другие вопросы по тегам:

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