- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在对一些类建模以表示 C# 中的度量单位。例如,我使用 IDistanceUnit
接口(interface)和基 DistanceUnit
类对毫米和英寸进行建模,提供通用的实现细节。
在每个具体类中都有这样定义的基本算术函数:
public class Inches :
DistanceUnit<Inches>,
IDistanceUnit,
INumericUnit<Inches, IDistanceUnit>
{
// ... snip ...
public Inches Add(IDistanceUnit unit)
{
return new Inches(Value + unit.ToInches().Value);
}
// ... snip ...
}
对转换为英寸和毫米的 10,000,000 次不同值的加法进行基准测试,但可以接受性能下降。手动执行转换的原始 double 大约需要 70-100 毫秒,而类大约需要 700-1000 毫秒。
我可以将细节抽象到 DistanceUnit
基类中并删除一些不必要的重复:
public abstract class DistanceUnit<TConcrete>
IDistanceUnit,
INumericUnit<TConcrete, IDistanceUnit>
where TConcrete :
IDistanceUnit,
INumericUnit<TConcrete, IDistanceUnit>,
new()
{
// ... snip ...
public TConcrete Add(IDistanceUnit unit)
{
TConcrete result = new TConcrete();
reuslt.Value = Value + ToThis(unit).Value();
return result;
}
// ... snip ...
}
// ToThis() calls the correct "ToXYZ()" for the current implementing class
这使我的表现至少又下降了 10 倍。与 800 毫秒相比,我看到大约 8000 毫秒,只是将实现移入基类。
我已经从手动测试中排除了一些事情:
ToThis(IDistanceUnit)
没有明显的变化在具体类而不是直接类中使用时性能下降调用“ToInches”或“ToMillimeters”new TConcrete()
)创建对象并赋值后来的值(value)最差的几毫秒的性能达到超过 10,000,000计算。我正在使用以下代码对我的结果进行基准测试:
int size = 10000000;
double[] mms = new double[size];
double[] inches = new double[size];
// Fill in some arbitrary test values
for (int i = 0; i < size; i++)
{
mms[i] = i;
inches[i] = i;
}
Benchmark("Manual Conversion", () =>
{
for (int i = 0; i < size; i++)
{
var result = mms[i] + (inches[i] * 25.4);
}
});
Benchmark("Unit Classes", () =>
{
for (int i = 0; i < size; i++)
{
var result = (new Millimeters(mms[i])) + (new Inches(inches[i]));
}
}
Benchmark 只是围绕提供的 Action 调用秒表,并打印出耗时(以毫秒为单位)。
唯一似乎造成主要差异的是 Add
函数从具体类移动到抽象基类,但我不明白为什么我会有一个几乎10 倍的性能下降。 谁能给我解释一下(如果可能的话,建议一种无需代码重复即可获得更快速度的方法)?
最佳答案
对于我在评论中所说的第一个性能命中,我需要了解一些实现细节:ToInches() 方法、ToThis() 方法、Value 属性的类型或代码。
对于第二次性能命中,最可能的原因是您对基类使用了 new() 约束并使用了
TConcrete result = new TConcrete();
编译器生成 Activator.CreateInstance<TConcrete>()
在这种情况下,此方法在引擎盖下使用反射并且速度很慢。如果你有数百万个实例化,它肯定会降低性能。 Here您可以从 Jon Skeet 那里找到一些基准。
如果您使用 >= 3.5 框架,您可以使用表达式树来构建基类中对象的快速通用实例化:
private static Func<TConcrete> _createFunc;
private static TConcrete CreateNew()
{
if (_func == null)
{
_createFunc = Expression.Lambda<Func<TConcrete>>(Expression.New(typeof (TConcrete))).Compile();
}
return _createFunc.Invoke();
}
public TConcrete Add(IDistanceUnit unit)
{
TConcrete result = CreateNew();
result.Value = Value + ToThis(unit).Value();
return result;
}
关于c# - 多态性能命中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16921053/
我来自 Asp.Net 世界,试图理解 Angular State 的含义。 什么是 Angular 状态?它类似于Asp.Net中的ascx组件吗?是子页面吗?它类似于工作流程状态吗? 我听到很多人
我一直在寻找 3 态拨动开关,但运气不佳。 基本上我需要一个具有以下状态的开关: |开 |不适用 |关 | slider 默认从中间开始,一旦用户向左或向右滑动,就无法回到N/A(未回答)状态。 有人
我是一名优秀的程序员,十分优秀!