- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个引擎,我们可以在运行时动态复制大量属性。根据情况,我们可能会也可能不会修改属性值。它最初是用反射写的,但是由于性能问题,我们最近在 Reflection.Emit
中重新写了它。重写完成,性能明显好很多,但现在代码正在与手写的 C#
进行基准测试。显然,为了公平起见,用于基准测试的手写 C#
与 IL
具有“相似的功能”(您很快就会明白我的意思) .
一些 IL
引擎已经被签署,因为它以优异的成绩通过了测试,并且与手写的 C#
几乎是 1:1 的。这告诉我:
调用动态方法没有开销
我们的总体概念和实现是正确的
基准测试是正确的
IL
和手写的 C#
正在以完全相同的方式进行测试,因此没有有趣的 JIT
业务在进行(我别想)
我们期望 IL
比手写的稍微慢一些,但到目前为止情况并非如此。在长回合中它可能会慢几毫秒,但您可以在 IL
中使用快捷方式,这样有助于弥补差异。
在一种特殊情况下,它的速度要慢得多。慢 2 倍。
在 C#
中,您将拥有:
class Source
{
public string S1 { get; set; }
public int I1 { get; set; }
public int I2 { get; set; }
public double D1 { get; set; }
public double D2 { get; set; }
public double D3 { get; set; }
}
class Dest
{
public string S1 { get; set; }
public int I1 { get; set; }
public string I2 { get; set; }
public double D1 { get; set; }
public int D2 { get; set; }
public string D3 { get; set; }
}
static Dest Test(Source s)
{
Dest d = new Dest();
object o = s.D3;
if (o != null)
d.D3 = o.ToString();
return d;
}
这就是我所说的类似功能的意思。为了通用,当我们将属性复制到字符串时,我们首先将其装箱,然后调用 Object.ToString()
。 native 地,值类型调用 ToString
不同,因此上面的代码是同类。
如果我注释掉 D3
copy/ToString
并取消注释其他 5 个属性,我将回到 1:1 与 C#
.
你会注意到 I2
是 int
-> string
,但出于某种原因,那个没有同样的问题与 double
-> string
一样。我知道 double ToString()
通常更昂贵,但该费用也应显示在 C# 代码中,但事实并非如此。
我为 D3
副本发出的代码与我为 I2
副本发出的代码相同,为什么 D3
的开销很大复制?
编辑:
编译器发出:
IL_0000: newobj instance void ConsoleApplication3.Dest::.ctor()
IL_0005: ldarg.0
IL_0006: callvirt instance float64 ConsoleApplication3.Source::get_D3()
IL_000b: box [mscorlib]System.Double
IL_0010: stloc.0
IL_0011: dup
IL_0012: ldloc.0
IL_0013: brtrue.s IL_0018
IL_0015: ldnull
IL_0016: br.s IL_001e
IL_0018: ldloc.0
IL_0019: callvirt instance string [mscorlib]System.Object::ToString()
IL_001e: callvirt instance void ConsoleApplication3.Dest::set_D3(string)
IL_0023: ret
我的代码的这个特定部分不会为 Dest 对象发出新的,这是在其他地方完成的。如上面的 C#
所示,dup 正在复制 Dest 对象。
LocalBuilder localBuilderObject = generator.DeclareLocal(_typeOfObject);
Label labelNull = generator.DefineLabel();
Label labelNotNull = generator.DefineLabel();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Callvirt, miGetter);
generator.Emit(OpCodes.Box, typeSource);
generator.Emit(OpCodes.Stloc_S, localBuilderObject);
generator.Emit(OpCodes.Dup);
generator.Emit(OpCodes.Ldloc_S, localBuilderObject);
generator.Emit(OpCodes.Brtrue, labelNotNull);
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Br, labelNull);
generator.MarkLabel(labelNotNull);
generator.Emit(OpCodes.Ldloc_S, localBuilderObject);
generator.Emit(OpCodes.Callvirt, _miToString);
generator.MarkLabel(labelNull);
generator.Emit(OpCodes.Callvirt,miSetter);
正如我提到的,我将类型框起来,这样我就可以一般地调用 Object::ToString()
而不必担心值类型。 Ref 类型也经过这条路径。 C#
代码被设计成这样,但仍然需要 1/2 的时间???
我整个周末都在处理这个问题。进一步测试显示其他值类型是 1:1。 int
、long
等。由于某种原因,double
导致了问题。
最佳答案
正如您在 C#
编译代码中所见,使用了快速本地访问指令:
IL_000b: box [mscorlib]System.Double
IL_0010: stloc.0
IL_0011: dup
IL_0012: ldloc.0
...
IL_0018: ldloc.0
相反,在您的 IL
生成的代码中,您使用 STLoc.s
和 ldloc.s
,它们也采用本地索引的操作数.
还要确保缓存(如果 C#
运行速度只快两倍,则可能是缓存)为每个 Type
生成的方法。
关于C# EMIT IL 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36961159/
如果我运行 .NET 编译器,它会生成一个包含中间语言代码 (IL) 的文件,并将其放入一个 .exe 文件(例如)。 如果我使用像 ildasm 这样的工具,它会再次显示 IL 代码。 但是,如果我
我正在努力寻找将为对象创建引用的位置以及将在哪个阶段创建它从程序到中间代码或中间代码到 native 代码. 最佳答案 This article might help : Typically, app
我正在尝试将这个简单的类转换为 IL 代码: public class IL { Dictionary props = new Dictionary() { {"1",1} }; } 事实上,在尝
我一直在查看有关 CLR Profiling API 的一些文章,其中许多文章都谈到调用 SetILFunctionBody() 来进行实际的 IL 重写;但是,这些文章都没有真正解释您可以使用什么来
C# 编译成 IL,然后很容易使用 ILSpy 或 dotPeek 反编译回 C#。 是否有任何工具可以将相同的 IL 反编译成 F#? 即是否有一种通过 IL 将 C# 转换为 F# 的偷偷摸摸的方
像 C# 方法 IL 一样发出 IL 但获取 System.InvalidProgramException:公共(public)语言运行时检测到无效程序。 示例: public static
我想为多线程应用程序生成 IL。作为第一步 我编写了一个简单的应用程序并使用 ILSpy 检查并生成了 IL。 public class ThreadTesting { public stat
是否有任何以 VS 插件或独立应用程序形式存在的 IL 级调试器? Visual Studio 的调试器很棒,但它允许您在 HLL 代码级别或汇编语言上进行调试,您无法调试 IL。 在某些情况下,有机
我已经编辑了简化它的问题 我有一个在这样的域中工作的应用程序: http://localhost:8092/myapp 如果我访问 http://localhost:8092/myapp/ticket
我正在使用2个选择标签。它们的内容可以在网页内修改(通过javascript)。 默认情况下,grails仅采用选定的选项(如果启用了多个,则为所有选定的选项),并将其传递给 Controller
您好,我试图通过grails在Windows控制台中运行一些命令。我这个代码 def pruebaMail() { "mkdir C:\\pruebaMail".execute()
这在html中工作正常,但在gsp中却不能。 反馈: GET http://translate.google.com/translate_tts?ie=utf-8&tl=en&q=hello%20w
我一直在研究 IL,我注意到类似 Prefix1 的操作码,文档基本上告诉我不用担心。当然,这让我很好奇这些不同的前缀操作码实际上是做什么的。谷歌快速搜索没有找到任何结果,所以我想我应该问问这里的专家
我是个新手。我现在在我的域类中遇到问题。我有3个域类,患者类,护士类和 NursePatient类, NursePatient类类是一个复合键,您可以在其中查看谁是患者的主治护士,因此,如果您查看其表
当我尝试从参数分配值时,它现在无法正常工作。 System.out.println(params.test) // I see 0 int test = params.test System.ou
如果我有一个程序集,我想更新一些文件,我需要用什么工具来执行此操作? 例如,在 java 中,可以解压缩 jar 文件更新所需的 .class 并重新压缩 jar。我怎样才能在 .NET 中完成同等的
public static class Extensions { public static T Include(this System.Enum type,T value) where T:
因此我需要对 DLL 文件进行非常简单的更改。 我已经使用 Reflector 成功地将 dll 文件导出为 IL 语言,并且找到了我需要进行的更改(它只是更改了一个 URL)。因此,如果我在记事本中
更多地考虑这是一个学术问题而不是实际问题。 在重新发明轮子时,即编写一个迷你 ORM/类型映射器时,我发出了一些 IL 以将对象的属性转换为添加到 SqlCommand 的 SqlParameters
很难学习“ float ”、“溢出”、“清除”和其他一些属性,所以请帮我找到好的在线网站来学习这些属性.. 我打开了一些网站来制作类似我发现的设计 http://wix.com我很欣赏它的导航栏,所以
我是一名优秀的程序员,十分优秀!