который имеет лучшую производительность? статика против объектов - PullRequest
3 голосов
/ 10 июня 2009

Я разработал консольное приложение C # для объединения и разделения огромных файлов (размером около 4 ГБ) с использованием ООП-дизайна. Это включает чтение / запись XML, плоских файлов и изображений. У меня есть занятия для читателей и писателей.

Слияние заняло около 00:12, а разделение заняло более 04:30 часов. Затем я увеличил производительность разделения до 00:50, распределяя выходные файлы по подкаталогам, а не используя один каталог.

Мой начальник просит меня преобразовать все в статическое процедурное программирование, но не объекты. Он говорит 00:12 для слияния по сравнению с 00:50 для разделения не сбалансировано. Он хочет, чтобы расщепление было выполнено в 00:30 минут путем преобразования в статическое.

Теперь я знаю, что статические вызовы быстрее в соответствии с этим . Однако я не согласен с тем, что все статические будут лучше, так как мне придется использовать параметры «ref» и «out» в методах.

Мои вопросы:

  1. В чем причина разбиения файлов в подкаталоге гораздо быстрее, чем при использовании одного выходного каталога? (то есть для большого количества файлов> 200 000)
  2. Есть ли лучший способ, чем преобразовать мой код из объекта в статический, для достижения более высокой производительности?

Ответы [ 7 ]

13 голосов
/ 10 июня 2009

Вы профилировали свою программу?

Вы должны профилировать свой код. Объекты быстрые, неоптимальный код невероятно медленный.

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

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

12 голосов
/ 10 июня 2009

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

Тайминги:

static: 154ms
instance: 156ms

Таким образом, разница в 2 мс по сравнению с 50 млн. Звонков! Забудь об этом ...

На основании:

class Program
{
    static void Main()
    {
        StaticMethod(); // JIT
        Program p = new Program();
        p.InstanceMethod(); // JIT

        const int LOOP = 50000000; // 50M
        Stopwatch watch = Stopwatch.StartNew();
        for (int i = 0; i < LOOP; i++) StaticMethod();
        watch.Stop();
        Console.WriteLine("static: " + watch.ElapsedMilliseconds + "ms");

        watch = Stopwatch.StartNew();
        for (int i = 0; i < LOOP; i++) p.InstanceMethod();
        watch.Stop();
        Console.WriteLine("instance: " + watch.ElapsedMilliseconds + "ms");
    }
    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
    void InstanceMethod() { }
    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
    static void StaticMethod() { }
}

редактирование:

Если мы предположим (например), что мы создаем новый метод каждые 20 вызовов (if (i % 20 == 0) p = new Program();), то метрики изменятся на:

static: 174ms
instance: 873ms

Опять же - недостаточно близко, чтобы указывать на узкое место, когда это более 50 миллионов вызовов, а у нас все еще меньше секунды!

6 голосов
/ 10 июня 2009

Ваша задача звучит так, как будто она должна быть привязана к IO, а не к CPU. Микро-оптимизация путем удаления правильного ОО-дизайна была бы безумием. Разница между статическими методами и методами экземпляров, как правило, неизмеримо мала (если вообще существует).

Как говорит Alamar, вы должны профилировать свое приложение, прежде чем идти дальше. Существует бесплатный профилировщик, доступный от Microsoft , или вы можете использовать JetBrains dotTrace profiler . Конечно, есть и другие - это те, которые я использовал.

Так же, как указание о том, связано ли оно с IO или с ЦП, если вы запускаете диспетчер задач во время работы приложения, сколько ЦП занимает процесс? И диск все время бьется?

Размещение большого количества файлов в каталоге замедлит доступ к этому каталогу, но только тогда, когда вы фактически создадите или откроете файл или перечислите файлы в каталоге. Я удивлен, это имеет такое большое значение, по общему признанию. Однако в любом случае наличие 200 000 файлов в каталоге звучит довольно неуправляемо. Использование иерархического подхода, вероятно, будет лучше с точки зрения использования этих файлов впоследствии.

Почему ваш начальник считает, что слияние и разделение должны занимать одинаковое количество времени?

3 голосов
/ 10 июня 2009

Я могу ответить на вопрос номер 1: наличие большого количества файлов в одном каталоге приводит к низкой производительности. Это не имеет никакого отношения к вашему коду - это вещь Windows (или NTFS, я не знаю). Разделение вещей по разным подкаталогам действительно значительно повышает производительность.

Что касается числа 2, я весьма сомневаюсь, что использование статических методов будет иметь огромное значение. Использование статических методов быстрее, но только незначительно . Мы говорим здесь микросекунды. Вероятно, что-то еще происходит. Есть только один способ выяснить это, как говорит alamar, профилировать ваш код.

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

2 голосов
/ 10 июня 2009

Мои ответы

  1. В зависимости от вашей ОС и файловой системы производительность начинает снижаться после 20-30 тыс. Файлов / подпапок. Это факт жизни. Производительность Ntfs и большие объемы файлов и каталогов

  2. Утверждение о том, что код без OO быстрее, чем код OO, повторяется. Вы не можете знать, какова ваша производительность, пока вы не профилируете код. См. Ответы на этот вопрос для хорошей информации Производительность анти-паттернов

0 голосов
/ 10 июня 2009
  1. Невозможно ответить на это, не зная вашего FS. Но, как отметили другие, FS обычно не оптимизированы для больших свернутых деревьев каталогов.
  2. Я думаю, что отклонение ООП из-за возможного (вы не профилировали) ~ увеличение скорости на 10% нелепо, особенно когда на странице написано: «Пожалуйста, не воспринимайте эти данные слишком буквально». 1006 *

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

0 голосов
/ 10 июня 2009

Многие файловые системы имеют проблемы с производительностью, когда количество записей в каталоге превышает определенный предел. Какой из них вы используете?

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

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