- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Test1
以下始终比 Test2
快 10% ,尽管我总是用 0
调用该方法参数,所以 switch case 里面的东西——唯一的区别——永远不会被执行。
顺便说一句,将代码复制并粘贴到一个全新的项目中后,只需将测试函数的名称更改为 Main
,结果反过来。每次我运行那个项目时,Test2
是比较快的。
那么是什么因素导致这个速度越来越慢呢?
和:我可以故意影响 .net 中的性能以对我有利吗?
这些方法当然几乎什么都不做,因此对于主要涉及相同虚拟方法调用的测试而言,10% 的性能差异似乎很大.
注意这实际上是真实程序的最小版本,其中多个嵌套的 switch 语句会导致巨大的性能差异,不仅是 10%,而且是 100% 甚至更多,这显然是因为测试的嵌套 switch 分支内仅存在代码永远不要进入。 (所以也许这个最小版本省略了可能涉及的真实程序的一些其他方面,但它确实复制了显着且一致的性能差异)
编辑 在实际程序中,可能比这个问题中的现象更重要的是 switch 语句中的实际 case 语句是否适合通过 branch table 实现。与否 - (这取决于案例值中的差距 - 我可以通过查看生成的 IL 代码来验证这一点)
试运行
using System;
using System.Diagnostics;
class Test1 : ITest
{
public int Test(int a)
{
switch (a)
{
case 1: return a + a + a == 1234 ? 1 : 2;
case 2: return 2;
}
return 0;
}
}
class Test2 : ITest
{
public int Test(int a)
{
switch (a)
{
case 1: return 1;
case 2: return 2;
}
return 0;
}
}
class Program
{
static void Main(string[] args)
{
const long iterations = 200000000;
var test1 = new Test1();
var test2 = new Test2();
while (true)
{
var sw1 = Stopwatch.StartNew();
for (long i = 0; i < iterations; i++)
test1.Test(0);
sw1.Stop();
var sw2 = Stopwatch.StartNew();
for (long i = 0; i < iterations; i++)
test2.Test(0);
sw2.Stop();
var iterPerUsec1 = iterations / sw1.Elapsed.TotalMilliseconds / 1000;
var iterPerUsec2 = iterations / sw2.Elapsed.TotalMilliseconds / 1000;
Console.WriteLine("iterations per usec: " + (int) iterPerUsec1 + " / " + (int) iterPerUsec2 + " ratio: " + iterPerUsec1/iterPerUsec2);
}
}
}
interface ITest
{
int Test(int a);
}
iterations per usec: 369 / 342 ratio: 1.07656329512607
iterations per usec: 367 / 314 ratio: 1.16820632522335
iterations per usec: 372 / 337 ratio: 1.10255744679504
iterations per usec: 374 / 342 ratio: 1.09248387354978
iterations per usec: 367 / 329 ratio: 1.11451205881061
iterations per usec: 375 / 340 ratio: 1.10041698470293
iterations per usec: 373 / 314 ratio: 1.19033461920118
iterations per usec: 366 / 334 ratio: 1.09808424282708
iterations per usec: 372 / 314 ratio: 1.18497411681768
iterations per usec: 377 / 342 ratio: 1.10482425370152
iterations per usec: 380 / 346 ratio: 1.09794853154766
iterations per usec: 385 / 342 ratio: 1.12737583603649
iterations per usec: 376 / 327 ratio: 1.15024393718844
iterations per usec: 374 / 332 ratio: 1.12400483908544
iterations per usec: 383 / 341 ratio: 1.12106159857722
iterations per usec: 380 / 345 ratio: 1.10267634674555
iterations per usec: 375 / 344 ratio: 1.09211401775982
iterations per usec: 384 / 334 ratio: 1.14958454236246
iterations per usec: 368 / 321 ratio: 1.14575850263002
iterations per usec: 378 / 335 ratio: 1.12732301818235
iterations per usec: 380 / 338 ratio: 1.12375853123099
iterations per usec: 386 / 344 ratio: 1.12213818994067
iterations per usec: 385 / 336 ratio: 1.14346447712043
iterations per usec: 374 / 345 ratio: 1.08448615249764
...
最佳答案
基准测试是一门艺术,像这样可靠地测量非常快的代码是非常困难的。一般来说,15% 或更少的差异在统计上并不显着。我只能评论已发布代码中的缺陷,这是一个很常见的缺陷。典型的海森堡式的,影响结果的是测试本身。
第二个 for() 循环不如第一个 for() 循环优化。由优化器选择将哪些局部变量存储在 CPU 寄存器中引起的问题。特别是在 32 位程序中使用 long 时的一个问题,它会烧毁两个 CPU 寄存器。很有可能,提到无法重现它的评论者使用 x64 抖动进行了测试。
通过将测试移到单独的方法中,您可以减轻 CPU 寄存器分配器的压力:
static Stopwatch runTest1(Test1 test1, long iterations) {
var sw1 = Stopwatch.StartNew();
for (long i = 0; i < iterations; i++)
test1.Test(0);
sw1.Stop();
return sw1;
}
static Stopwatch runTest2(Test2 test2, long iterations) {
var sw2 = Stopwatch.StartNew();
for (long i = 0; i < iterations; i++)
test2.Test(0);
sw2.Stop();
return sw2;
}
static void Main(string[] args) {
const long iterations = 200000000;
var test1 = new Test1();
var test2 = new Test2();
while (true) {
var sw1 = runTest1(test1, iterations);
var sw2 = runTest2(test2, iterations);
// etc..
}
}
for (long i = 0; i < iterations; i++)
00000089 xor ebx,ebx
0000008b xor esi,esi
0000008d mov ecx,dword ptr [esp+4]
00000091 xor edx,edx
00000093 call dword ptr ds:[04732844h]
00000099 add ebx,1
0000009c adc esi,0
0000009f test esi,esi
000000a1 jg 000000AD
000000a3 jl 0000008D
000000a5 cmp ebx,0BEBC200h
000000ab jb 0000008D
for (long i = 0; i < iterations; i++)
000000f5 mov dword ptr [esp+2Ch],0
000000fd xor ebx,ebx
000000ff mov ecx,dword ptr [esp]
00000102 xor edx,edx
00000104 call dword ptr ds:[056E28B8h]
0000010a mov eax,ebx
0000010c mov edx,dword ptr [esp+2Ch] ; <== here
00000110 add eax,1
00000113 adc edx,0
00000116 mov dword ptr [esp+2Ch],edx ; <== here
0000011a mov ebx,eax
0000011c cmp dword ptr [esp+2Ch],0
00000121 jg 0000012D
00000123 jl 000000FF
00000125 cmp ebx,0BEBC200h
0000012b jb 000000FF
关于.net - 当唯一的区别在于未执行的代码路径时,为什么性能会有所不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31309289/
尝试使用集成到 QTCreator 的表单编辑器,但即使我将插件放入 QtCreator.app/Contents/MacOS/designer 也不会显示。不过,相同的 dylib 文件确实适用于独
在此代码示例中。 “this.method2();”之后会读到什么?在返回returnedValue之前会跳转到method2()吗? public int method1(int returnedV
我的项目有通过gradle配置的依赖项。我想添加以下依赖项: compile group: 'org.restlet.jse', name: 'org.restlet.ext.apispark', v
我将把我们基于 Windows 的客户管理软件移植到基于 Web 的软件。我发现 polymer 可能是一种选择。 但是,对于我们的使用,我们找不到 polymer 组件具有表格 View 、下拉菜单
我的项目文件夹 Project 中有一个文件夹,比如 ED 文件夹,当我在 Eclipse 中指定在哪里查找我写入的文件时 File file = new File("ED/text.txt"); e
这是奇怪的事情,这个有效: $('#box').css({"backgroundPosition": "0px 250px"}); 但这不起作用,它只是不改变位置: $('#box').animate
这个问题在这里已经有了答案: Why does OR 0 round numbers in Javascript? (3 个答案) 关闭 5 年前。 Mozilla JavaScript Guide
这个问题在这里已经有了答案: Is the function strcmpi in the C standard libary of ISO? (3 个答案) 关闭 8 年前。 我有一个问题,为什么
我目前使用的是共享主机方案,我不确定它使用的是哪个版本的 MySQL,但它似乎不支持 DATETIMEOFFSET 类型。 是否存在支持 DATETIMEOFFSET 的 MySQL 版本?或者有计划
研究 Seam 3,我发现 Seam Solder 允许将 @Named 注释应用于包 - 在这种情况下,该包中的所有 bean 都将自动命名,就好像它们符合条件一样@Named 他们自己。我没有看到
我知道 .append 偶尔会增加数组的容量并形成数组的新副本,但 .removeLast 会逆转这种情况并减少容量通过复制到一个新的更小的数组来改变数组? 最佳答案 否(或者至少如果是,则它是一个错
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
noexcept 函数说明符是否旨在 boost 性能,因为生成的对象中可能没有记录异常的代码,因此应尽可能将其添加到函数声明和定义中?我首先想到了可调用对象的包装器,其中 noexcept 可能会产
我正在使用 Angularjs 1.3.7,刚刚发现 Promise.all 在成功响应后不会更新 angularjs View ,而 $q.all 会。由于 Promises 包含在 native
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我正在编写一个玩具(物理)矢量库,并且遇到了 GHC 坚持认为函数应该具有 Integer 的问题。是他们的类型。我希望向量乘以向量以及标量(仅使用 * ),虽然这可以通过仅使用 Vector 来实现
PHP 的 mail() 函数发送邮件正常,但 Swiftmailer 的 Swift_MailTransport 不起作用! 这有效: mail('user@example.com', 'test
我尝试通过 php 脚本转储我的数据,但没有命令行。所以我用 this script 创建了我的 .sql 文件然后我尝试使用我的脚本: $link = mysql_connect($host, $u
使用 python 2.6.4 中的 sqlite3 标准库,以下查询在 sqlite3 命令行上运行良好: select segmentid, node_t, start, number,title
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我是一名优秀的程序员,十分优秀!