gpt4 book ai didi

c# - 具有可空值类型的 as 运算符是否不必要地慢?

转载 作者:太空狗 更新时间:2023-10-29 19:45:23 25 4
gpt4 key购买 nike

考虑这段代码:

static void FillUsingAsNullable()
{
int?[] arr = new int?[1 << 24];
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < arr.Length; ++i)
arr[i] = GetObject() as int?;
Console.WriteLine("{0:N0}", sw.ElapsedTicks);
}

static void FillUsingOwnCode()
{
int?[] arr = new int?[1 << 24];
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < arr.Length; ++i)
{
object temporary = GetObject();
arr[i] = temporary is int ? (int?)temporary : null;
}
Console.WriteLine("{0:N0}", sw.ElapsedTicks);
}

static object GetObject()
{
//Uncomment only one:
//return new object();
//return 42;
//return null;
}

据我所知,方法 FillUsingAsNullableFillUsingOwnCode应该是等价的。

但看起来“自己的代码”版本显然更快。

2编译“x86”或“x64”的选择,以及2编译“调试”或“发布(优化)”的选择,以及 3 GetObject 返回内容的选择方法。据我所知,在所有这些2*2*3 == 12在某些情况下,“自己的代码”版本明显快于“可空”版本。

问题:是asNullable<>不必要的慢,或者我在这里遗漏了什么(很有可能)?

相关主题:Performance surprise with “as” and nullable types .

最佳答案

生成的 IL 有所不同,但并非根本不同。如果 JIT 很好(事实并非如此,这不是新闻),它可以编译为完全相同的 x86 代码。

我用 VS2010 Release AnyCPU 编译了这个。

作为版本:

L_0015: call object ConsoleApplication3.Program::GetObject()
L_001a: stloc.3
L_001b: ldloc.0
L_001c: ldloc.2
L_001d: ldelema [mscorlib]System.Nullable`1<int32>
L_0022: ldloc.3
L_0023: isinst [mscorlib]System.Nullable`1<int32>
L_0028: unbox.any [mscorlib]System.Nullable`1<int32>
L_002d: stobj [mscorlib]System.Nullable`1<int32>

?: 版本:

L_0015: call object ConsoleApplication3.Program::GetObject()
L_001a: stloc.3
L_001b: ldloc.0
L_001c: ldloc.2
L_001d: ldelema [mscorlib]System.Nullable`1<int32>
L_0022: ldloc.3
L_0023: isinst int32
L_0028: brtrue.s L_0036 //**branch here**
L_002a: ldloca.s nullable
L_002c: initobj [mscorlib]System.Nullable`1<int32>
L_0032: ldloc.s nullable
L_0034: br.s L_003c
L_0036: ldloc.3
L_0037: unbox.any [mscorlib]System.Nullable`1<int32>
L_003c: stobj [mscorlib]System.Nullable`1<int32>

操作码的描述在 MSDN 上。理解这个 IL 并不困难,任何人都可以做到。不过,对于没有经验的人来说,这有点费时。

主要区别在于源代码中有分支的版本在生成的IL中也有分支。它只是有点不那么优雅。如果 C# 编译器愿意,它可以优化它,但团队的策略是让 JIT 担心优化。如果 JIT 获得当时必要的投资,将会很好地工作。

您可以通过查看 JIT 发出的 x86 来进一步分析这一点。你会发现一个明显的不同,但这将是一个不起眼的发现。我不会花时间去做那件事。


我修改了 as 版本以使用一个临时的以及有一个公平的比较:

            var temporary = GetObject();
arr[i] = temporary as int?;

关于c# - 具有可空值类型的 as 运算符是否不必要地慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21389670/

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