ILSpy显示String.IsNullOrEmpty
是通过String.Length
实现的。但是为什么String.IsNullOrEmpty(s)
比s.Length == 0
更快呢?
例如,在这个基准测试中,它比后者快5%:
var stopwatches = Enumerable.Range(0, 4).Select(_ => new Stopwatch()).ToArray();
var strings = "A,B,,C,DE,F,,G,H,,,,I,J,,K,L,MN,OP,Q,R,STU,V,W,X,Y,Z,".Split(',');
var testers = new Func<string, bool>[] { s => s == String.Empty, s => s.Length == 0, s => String.IsNullOrEmpty(s), s => s == "" };
int count = 0;
for (int i = 0; i < 10000; ++i) {
stopwatches[i % 4].Start();
for (int j = 0; j < 1000; ++j)
count += strings.Count(testers[i % 4]);
stopwatches[i % 4].Stop();
}
(其他基准测试显示类似的结果。这个测试最小化了在我的计算机上运行的无用程序的影响。另外,顺带一提,与空字符串比较的测试结果与使用IsNullOrEmpty
相比慢了约13%。)
此外,为什么IsNullOrEmpty
只在x86架构上更快,而在x64架构上String.Length
大约快9%?
更新: 测试设置详情: 在64位Windows 7操作系统上运行.NET 4.0,使用英特尔Core i5处理器,编译时启用"优化代码"选项。但是,“在模块加载时禁止JIT优化”也已启用(请参见接受的答案和评论)。
在完全启用优化的情况下,Length
比IsNullOrEmpty
快约14%,并且去除了委托和其他开销,在这个测试中得出如下结果:
var strings = "A,B,,C,DE,F,,G,H,,,,I,J,,K,L,MN,OP,Q,R,,STU,V,,W,,X,,,Y,,Z,".Split(',');
int count = 0;
for (uint i = 0; i < 100000000; ++i)
count += strings[i % 32].Length == 0 ? 1 : 0; // Replace Length test with String.IsNullOrEmpty