2013-04-15 3 views
3

Хотя я отметил этот вопрос с помощью службы SSIS, это не обязательно относится к моему вопросу; Поэтому, пожалуйста, продолжайте читать, если вы знакомы с проблемами анализа и анализа производительности .NET, как правило, вы можете помочь!Выполнение выполнения метода позднего метода вызова против выбора метода выбора/выбора

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

Я обновляю уже существующий пользовательский контроль потока данных.

Для каждого столбца в строке код должен выполнить конкретный метод в экземпляре (строке) Microsoft.SqlServer.Dts.Pipeline.PipelineBuffer в зависимости от типа данных SSIS (столбца).

Например,

public override void ProcessInput(int inputID, PipelineBuffer buffer) 
{ 
    ... 
    while (!buffer.EndOfRowset && buffer.NextRow()) 
    { 
     ... 
     someStringAtColumn1 = buffer.GetString(1); 
     someIntAtColumn2 = buffer.GetInt16(2); 
     someBoolAtColumn3 = buffer.GetBoolean(3); 

     // And so on, for up to ~25 different types.... 
    } 
    ... 
} 

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

С этой целью был использован (и работает) шаблон, опубликованный в SSIS Junkie SSIS: Generic method for populating a pipeline buffer column. Таким образом, это использует SWITCH (buffer.GetColumnInfo(columnIndex).DataType), чтобы решить, какой из 25 методов для вызова buffer.

Итак, мои вопросы:

  1. повторяет этот SWITCH заявление для каждого столбца (число изменяется для каждой таблицы, но, скажем, в среднем 10 столбцов) для каждой строки (потенциально миллионы), вероятно, для значительного воздействия на производительность (с точки зрения времени обработки)?

  2. Было бы лучше до конца привязки к правильному методу для каждого столбца, на основе за стол (т.е. до начала строки за строкой обработки), а затем выполняет этот столбец конкретного поздно -bound для каждого столбца (во время обработки строки за строкой)?

Подход, который я думал бы что-то вроде:

// Set up per-column late-bound methods, once, prior to processing the rows 
    System.Reflection.MethodInfo[] lateBoundMethods; 

    //Psuedo code here for brevity... 
    foreach column in tableDefinition { 
     lateBoundMethods[i++] = getColumnSpecificGetValueMethod(column.DataType); 
    } 
    //End of psuedo code 


private System.Reflection.MethodInfo getColumnSpecificGetValueMethod(DataType dataType) 
{ 
    string methodName = ""; 

    switch (dataType) 
    { 
     case DataType.DT_BOOL: 
      methodName = "GetBoolean"; 
      break; 
     case DataType.DT_BYTES: 
      methodName = "GetBytes"; 
      break; 
     case DataType.DT_CY: 
      methodName = "GetDecimal"; 
      break; 

      ... 

     case DataType.DT_WSTR: 
      methodName = "GetString"; 
      break; 
     default: 
      return null; //TODO: Throw an exception? 
    } 

    System.Reflection.MethodInfo methodInfo = typeof(PipelineBuffer).GetMethod(
     methodName, 
     System.Reflection.BindingFlags.ExactBinding | 
     System.Reflection.BindingFlags.Instance | 
     System.Reflection.BindingFlags.Public); 

    return methodInfo; 
} 

private object getValueFromBuffer(PipelineBuffer buffer, int columnIndex) 
{ 
    if (buffer.IsNull(columnIndex)) 
    { 
     return null; 
    } 
    return lateBoundMethods[columnIndex].Invoke(buffer, new object[] { columnIndex}); 
} 

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

Object columnValue = getValueFromBuffer(buffer, columnIndex);.

Так что я думаю, вопрос 2 сводится к «ли выполнение .Invoke против уже -связанного MethodInfo будет быстрее, чем выполнение большого переключателя/случая?».

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

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

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

Ваше время и ввод оценены!

ответ

0

Вы, кажется, используете отражение для каждой строки, что было бы ужасно медленным. Я бы предложил использовать словарь вместо оператора switch и кэшировать отраженный метод (например, отражать только один раз за метод = ~ 25 раз + N словарных поисков вместо N разного отражения). Это значительно улучшит производительность.

Окончательный ответ, конечно же, будет написание быстрого прототипа и запуск профилировщика, как вы предлагаете.

+0

Перед обработкой строк я предложил использовать .GetMethod() _once_ за столбец. И используя .Invoke() один раз за столбец за строку. Вы говорите, что .Invoke() работает медленно, хотя метод для вызова уже был отражен ранее? – Sepster

+1

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

+0

Действительно, я, кажется, пропустил это. Спасибо за повторную проверку! – ya23

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