2012-02-10 4 views
0

У меня есть хранимая процедура, которая возвращает несколько результирующих наборов и внутри (некоторых) результатов 1000 строк. Я выполняю эту сохраненную процедуру, используя x потоков одновременно, с максимумом y одновременно.Производительность процессора при создании большого количества объектов с помощью SqlDataReader

Когда я только пробежать данные:

using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection)) 
{ 
    do 
    { 
     while (reader.Read()) 
     { 
      for (int i = 0; i < reader.FieldCount; i++) 
      { 
       var value = reader.GetValue(i); 
      } 
     } 
    } 
    while (reader.NextResult()); 
} 

я получаю достаточную пропускную способность - и CPU. Теперь, очевидно, это бесполезно, поэтому мне нужны некоторые объекты! Хорошо, теперь я изменить его, чтобы сделать что-то вроде этого:

using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection)) 
{ 
    while(reader.Read()) 
    { 
     Bob b = new Bob(reader); 
     this.bobs.Add(b);    
    } 

    reader.NextResult(); 

    while(reader.Read()) 
    { 
     Clarence c = new Clarence(reader); 
     this.clarences.Add(c); 
    } 

    // More fun 
} 

И моя реализация классов данных:

public Bob(SqlDataReader reader) 
{ 
    this.some = reader.GetInt32(0); 
    this.parameter = reader.GetInt32(1); 
    this.value = reader.GetString(2); 
} 

И это работает хуже. Что неудивительно. То, что удивительно, заключается в том, что CPU падает и примерно на 20-25% от общего количества (т. Е. Не 25% от того, что он использовал, он близок к 50% того, что он использовал)! Зачем делать больше работы, бросать процессор? Я не понимаю ... похоже, что где-то есть где-то, но я не понимаю, где? Я хочу получить максимальную отдачу от машины!

EDIT - измененный код из-за плохого примера демонстрационного кода. К сожалению.

ТАКЖЕ: для проверки теории конструктора я изменил реализацию той, которая создает объект. На этот раз он также выполняет цикл for по полям и делает getValue и создает пустой объект. Таким образом, он не делает то, что я хочу, да, но я хотел видеть, является ли проблема с созданием большого количества объектов. Это не так.

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

+0

Спасибо, Тим, но это не полезно; это просто показать, что я делаю. bob & clarence - это, очевидно, вздор. Вы можете предположить, что код не является исключением. Проблема не исключение, проблема в том, что процессор падает. Коллекции не могут быть статическими, так как я использую это ключевое слово Метод не может быть статическим, поскольку он является конструктором .... – peteisace

+0

% Использование ЦП - это одна метрика, которая сообщает вам, как сильно он ударяет по ЦПУ в любой момент - другой во время выполнения. Сколько времени занимает первый пример, и сколько времени занимает второе? –

+0

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

ответ

0

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

Ваш лучший выбор - запустить это через профилировщик и взглянуть на отчет.

+0

Предыдущая попытка: я собираюсь опасаться, что это связано с оптимизацией, вы ничего не делаете с помощью var в первом примере, и компилятор может просто сказать «ничего не делать» или где-либо между полным исполнением и без выполнения. В вашем втором примере есть вызовы 'this.clarences' и' this.bobs', поэтому, возможно, такая же оптимизация не будет применяться, эти переменные должны быть изменены. –

+0

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

1

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

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

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

1

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

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

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

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

Для того, чтобы определить, даже выше, вы должны установить счетчики часов на количество памяти, используемое приложением, и количество доступной ОЗУ. Кроме того, вам понадобятся счетчики на вашей дисковой системе, чтобы узнать, сильно ли он доступен в любом сценарии.

Точка есть, попробуйте и посмотрите ВСЕ, что происходит в машине, пока блоки кода работают. Это даст вам лучшее представление о том, почему процессор ожидает.

+0

как в основном через материал ... первая версия выбрасывает значение, вторая версия бросает объект, содержащий коллекции. ничто из этого не висит вокруг. mem в два раза (45k против 20k) - первая версия. сеть и т. д. ниже во второй версии. – peteisace

+0

@peteisace: Уверен, что второй выброшен, но его на совершенно другой уровень. Независимо от того, что вам абсолютно необходимо посмотреть счетчики производительности всей системы. Процессор в основном отключается, пока он ждет другую часть вашей системы (память, диск, сеть ..). Вам нужно узнать, что ждет. – NotMe

Смежные вопросы