gpt4 book ai didi

.net - 执行后期绑定(bind)方法调用与 switch/case 方法选择的性能

转载 作者:行者123 更新时间:2023-12-02 05:01:25 25 4
gpt4 key购买 nike

虽然我用 SSIS 标记了这个问题,但它不一定是我问题的核心;因此,如果您通常熟悉 .NET 反射和代码性能问题,请继续阅读,因为您可能会有所帮助!

但特别是,关联代码将被执行多次(即针对数据源逐行执行)这一事实是关键。

我正在更新预先存在的自定义数据流控件。

对于一行中的每一列,代码必须根据(列)SSIS 数据类型对 Microsoft.SqlServer.Dts.Pipeline.PipelineBuffer 实例(行)执行特定方法。

例如,

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 JunkieSSIS: Generic method for populating a pipeline buffer column已被使用(和工作)。总之,这使用 SWITCH (buffer.GetColumnInfo(columnIndex).DataType) 来决定调用 buffer 的 ~25 种方法中的哪一种。

那么,我的问题:

  1. 正在为每一行(可能是数百万)重复此 SWITCH 语句(每个表的数量各不相同,但假设平均 10 列),可能会导致显着的性能影响(在处理时间方面)?

  2. 在每个表的基础上(即逐行处理开始之前)为每一列延迟绑定(bind)到正确的方法是否更好,然后对每一列执行特定于列的后期绑定(bind)方法(在逐行处理期间)?

我想到的方法是这样的:

// 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 来对抗 已经-bound MethodInfo 将是比执行大开关/案例更快?”。

编辑:我很欣赏反射通常被认为是缓慢的。但是根据上面的大胆问题,我不清楚反射的哪些部分是缓慢的。我很高兴在预执行设置阶段表现不佳,只要调用后期绑定(bind)方法比处理行时选择调用哪些方法更快。因此,对于任何说明这会很慢的回答,您能否澄清一下,您认为是后期绑定(bind)方法的调用会很慢,而不是确定要绑定(bind)哪个方法的任务。

我意识到没有比运行一些测试更明确的答案了……但我一直在预先寻找一些(合理的)权威指示,然后再投入大量精力,因为将 ETL 部署到我们的 TEST 环境中进行性能测试是非常重要。

此外,我愿意听取有关其他更好方法的建议。

感谢您的宝贵时间和意见!

最佳答案

您似乎对每一行都使用了反射,这会非常慢。我建议您使用字典而不是 switch 语句并缓存反射的方法(例如,每个方法只反射一次 = ~25 次 + N 次字典查找而不是 N 次反射)。这将大大提高性能。

最终的答案当然是按照您的建议编写快速原型(prototype)并运行分析器。

关于.net - 执行后期绑定(bind)方法调用与 switch/case 方法选择的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16009925/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com