- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在读Pro .net Performance书。它指出:
以下是托管方法的典型序言和结尾
编译为32位机器代码(这不是实际的生产代码
由JIT编译器制作,并进行了大量优化
在第10章中讨论)。该方法有四个局部变量,它们的
在序言中立即分配存储,并在其中立即回收
结语:
书籍声称这种方法:
int Calculation(int a, int b)
{
int x = a + b;
int y = a - b;
int z = b - a;
int w = 2 * b + 2 * a;
return x + y + z + w;
}
; parameters are passed on the stack in [esp+4] and [esp+8]
push ebp
mov ebp, esp
add esp, 16 ; allocates storage for four local variables
mov eax, dword ptr [ebp+8]
add eax, dword ptr [ebp+12]
mov dword ptr [ebp-4], eax
; ...similar manipulations for y, z, w
mov eax, dword ptr [ebp-4]
add eax, dword ptr [ebp-8]
add eax, dword ptr [ebp-12]
add eax, dword ptr [ebp-16] ; eax contains the return value
mov esp, ebp ; restores the stack frame, thus reclaiming the local storage space
pop ebp
ret 8 ; reclaims the storage for the two parameters
class TestCall
{
public static void Main(string[] args)
{
TestCall testCall=new TestCall();
int sum=0;
for (int i = 0; i < 5; i++)
{
sum += testCall.Calculation(5, 6);
}
Console.WriteLine(sum);
}
int Calculation(int a, int b)
{
int x = a + b;
int y = a - b;
int z = b - a;
int w = 2 * b + 2 * a;
return x + y + z + w;
}
}
Calculation
方法:
23: {
005B2EB8 push ebp
005B2EB9 mov ebp,esp
005B2EBB push edi
005B2EBC push esi
005B2EBD push ebx
005B2EBE sub esp,48h
005B2EC1 mov esi,ecx
005B2EC3 lea edi,[ebp-38h]
005B2EC6 mov ecx,0Bh
005B2ECB xor eax,eax
005B2ECD rep stos dword ptr es:[edi]
005B2ECF mov ecx,esi
005B2ED1 mov dword ptr [ebp-3Ch],ecx
005B2ED4 mov dword ptr [ebp-40h],edx
005B2ED7 cmp dword ptr ds:[12C668h],0
005B2EDE je 005B2EE5
005B2EE0 call 6970CB2D
005B2EE5 xor edx,edx
005B2EE7 mov dword ptr [ebp-54h],edx
005B2EEA xor edx,edx
005B2EEC mov dword ptr [ebp-4Ch],edx
005B2EEF xor edx,edx
005B2EF1 mov dword ptr [ebp-50h],edx
005B2EF4 xor edx,edx
005B2EF6 mov dword ptr [ebp-48h],edx
005B2EF9 xor edx,edx
005B2EFB mov dword ptr [ebp-44h],edx
005B2EFE nop
24: int x = a + b;
005B2EFF mov eax,dword ptr [ebp-40h]
005B2F02 add eax,dword ptr [ebp+8]
005B2F05 mov dword ptr [ebp-44h],eax
25: int y = a - b;
005B2F08 mov eax,dword ptr [ebp-40h]
005B2F0B sub eax,dword ptr [ebp+8]
005B2F0E mov dword ptr [ebp-48h],eax
26: int z = b - a;
005B2F11 mov eax,dword ptr [ebp+8]
005B2F14 sub eax,dword ptr [ebp-40h]
005B2F17 mov dword ptr [ebp-4Ch],eax
27: int w = 2*b + 2*a;
005B2F1A mov eax,dword ptr [ebp+8]
005B2F1D add eax,eax
005B2F1F mov edx,dword ptr [ebp-40h]
27: int w = 2*b + 2*a;
005B2F22 add edx,edx
005B2F24 add eax,edx
005B2F26 mov dword ptr [ebp-50h],eax
28: return x + y + z + w;
005B2F29 mov eax,dword ptr [ebp-44h]
005B2F2C add eax,dword ptr [ebp-48h]
005B2F2F add eax,dword ptr [ebp-4Ch]
005B2F32 add eax,dword ptr [ebp-50h]
005B2F35 mov dword ptr [ebp-54h],eax
005B2F38 nop
005B2F39 jmp 005B2F3B
29: }
005B2F3B mov eax,dword ptr [ebp-54h]
005B2F3E lea esp,[ebp-0Ch]
005B2F41 pop ebx
005B2F42 pop esi
005B2F43 pop edi
005B2F44 pop ebp
005B2F45 ret 4
最佳答案
不要从调试器运行应用程序。而是将类似Debugger.Launch
的内容放入代码中,然后运行而无需调试。当您在调试器中启动时,JIT编译器会针对调试进行优化,此处您要避免这种情况。
我在调试器中运行32位调试版本,
002E2EC2 in al,dx
002E2EC3 push edi
002E2EC4 push esi
002E2EC5 push ebx
002E2EC6 sub esp,48h
002E2EC9 mov esi,ecx
002E2ECB lea edi,[ebp-38h]
002E2ECE mov ecx,0Bh
002E2ED3 xor eax,eax
002E2ED5 rep stos dword ptr es:[edi]
002E2ED7 mov ecx,esi
002E2ED9 mov dword ptr [ebp-3Ch],ecx
002E2EDC mov dword ptr [ebp-40h],edx
002E2EDF cmp dword ptr ds:[28C670h],0
002E2EE6 je 002E2EED
002E2EE8 call 730FCB2D
002E2EED xor edx,edx
002E2EEF mov dword ptr [ebp-54h],edx
002E2EF2 xor edx,edx
002E2EF4 mov dword ptr [ebp-4Ch],edx
002E2EF7 xor edx,edx
002E2EF9 mov dword ptr [ebp-50h],edx
002E2EFC xor edx,edx
002E2EFE mov dword ptr [ebp-48h],edx
002E2F01 xor edx,edx
002E2F03 mov dword ptr [ebp-44h],edx
002E2F06 nop
int x = a + b;
002E2F07 mov eax,dword ptr [ebp-40h]
002E2F0A add eax,dword ptr [ebp+8]
002E2F0D mov dword ptr [ebp-44h],eax
int y = a - b;
002E2F10 mov eax,dword ptr [ebp-40h]
int y = a - b;
002E2F13 sub eax,dword ptr [ebp+8]
002E2F16 mov dword ptr [ebp-48h],eax
int z = b - a;
002E2F19 mov eax,dword ptr [ebp+8]
002E2F1C sub eax,dword ptr [ebp-40h]
002E2F1F mov dword ptr [ebp-4Ch],eax
int w = 2 * b + 2 * a;
002E2F22 mov eax,dword ptr [ebp+8]
002E2F25 add eax,eax
002E2F27 mov edx,dword ptr [ebp-40h]
002E2F2A add edx,edx
002E2F2C add eax,edx
002E2F2E mov dword ptr [ebp-50h],eax
return x + y + z + w;
002E2F31 mov eax,dword ptr [ebp-44h]
002E2F34 add eax,dword ptr [ebp-48h]
002E2F37 add eax,dword ptr [ebp-4Ch]
002E2F3A add eax,dword ptr [ebp-50h]
002E2F3D mov dword ptr [ebp-54h],eax
002E2F40 nop
002E2F41 jmp 002E2F43
00350543 sub esp,20h
00350546 xor eax,eax
00350548 mov dword ptr [ebp-20h],eax
0035054B mov dword ptr [ebp-4],ecx
0035054E mov dword ptr [ebp-8],edx
00350551 cmp dword ptr ds:[1D4268h],0
00350558 je 0035055F
0035055A call 730FCB2D
0035055F xor edx,edx
00350561 mov dword ptr [ebp-0Ch],edx
00350564 xor edx,edx
00350566 mov dword ptr [ebp-1Ch],edx
00350569 xor edx,edx
0035056B mov dword ptr [ebp-14h],edx
0035056E xor edx,edx
00350570 mov dword ptr [ebp-18h],edx
00350573 xor edx,edx
00350575 mov dword ptr [ebp-10h],edx
00350578 nop
Debugger.Launch();
00350579 call 725B0220
0035057E mov dword ptr [ebp-20h],eax
00350581 nop
Debugger.Break();
00350582 call 725B0178
00350587 nop
int x = a + b;
00350588 mov eax,dword ptr [ebp-8]
int x = a + b;
0035058B add eax,dword ptr [ebp+8]
0035058E mov dword ptr [ebp-0Ch],eax
int y = a - b;
00350591 mov eax,dword ptr [ebp-8]
00350594 sub eax,dword ptr [ebp+8]
00350597 mov dword ptr [ebp-10h],eax
int z = b - a;
0035059A mov eax,dword ptr [ebp+8]
0035059D sub eax,dword ptr [ebp-8]
003505A0 mov dword ptr [ebp-14h],eax
int w = 2 * b + 2 * a;
003505A3 mov eax,dword ptr [ebp+8]
003505A6 add eax,eax
003505A8 mov edx,dword ptr [ebp-8]
003505AB add edx,edx
003505AD add eax,edx
003505AF mov dword ptr [ebp-18h],eax
return x + y + z + w;
003505B2 mov eax,dword ptr [ebp-0Ch]
003505B5 add eax,dword ptr [ebp-10h]
003505B8 add eax,dword ptr [ebp-14h]
003505BB add eax,dword ptr [ebp-18h]
003505BE mov dword ptr [ebp-1Ch],eax
003505C1 nop
003505C2 jmp 003505C4
000007FE94220495 xor esi,esi
for (int i = 0; i < 5; i++)
000007FE94220497 xor edi,edi
{
sum += testCall.Calculation(5, 6);
000007FE94220499 call 000007FEF2FB7AB0
000007FE9422049E call 000007FEF2FB79C0
000007FE942204A3 add esi,21h
for (int i = 0; i < 5; i++)
000007FE942204A6 inc edi
000007FE942204A8 cmp edi,5
000007FE942204AB jl 000007FE94220499
}
Console.WriteLine(sum);
000007FE942204AD mov ecx,esi
000007FE942204AF call 000007FEF2FBAC10
000007FE942204B4 nop
000007FE942204B5 add rsp,28h
000007FE942204B9 pop rsi
000007FE942204BA pop rdi
000007FE942204BB ret
Debugger.Launch
和
Debugger.Break
。循环的整个过程就是
000007FE942204A3 add esi,21h
sum
变量增加21h(注意它不在堆栈中)?
x + y == 2 * a
(x + y + z) == a + b
(x + y + z + w) == 3 * a + 3 * b
a
始终为5,
b
始终为6,因此该函数始终返回33,即21h。因此,编译器“足够聪明”,但是对于判断.NET中的函数调用不是很有用。
virtual
,这样编译器就无法确定到底要调用哪种方法,从而防止内联。另外,您可以使用
Debugger.Launch();
000007FE94220530 push rdi
000007FE94220531 push rsi
000007FE94220532 sub rsp,28h
000007FE94220536 mov esi,edx
000007FE94220538 mov edi,r8d
000007FE9422053B call 000007FEF2FB7AB0
Debugger.Break();
000007FE94220540 call 000007FEF2FB79C0
int x = a + b;
000007FE94220545 mov eax,esi
000007FE94220547 sub eax,edi
000007FE94220549 mov edx,edi
000007FE9422054B sub edx,esi
000007FE9422054D mov ecx,esi
000007FE9422054F shl ecx,1
000007FE94220551 lea ecx,[rcx+rdi*2]
000007FE94220554 lea r8d,[rsi+rdi]
000007FE94220558 add eax,r8d
000007FE9422055B add eax,edx
000007FE9422055D add eax,ecx
000007FE9422055F add rsp,28h
000007FE94220563 pop rsi
000007FE94220564 pop rdi
000007FE94220565 ret
NoInlining
?我不知道。也许对调试或异常处理有所帮助?我对此只能猜测。但它当然与功能的正常运行无关。随后的移动(将参数移至其他寄存器)是针对我的CPU(2012 Xeon)量身定制的-它允许更好的流水线处理。我不确定启发式算法是如何工作的以及针对特定CPU或CPU系列的尝试程度,但是对于我的系统而言,它当然非常有用:)您期望这种代码比手动天真的汇编慢一些,但是不是。流水线和分支预测是当今CPU吞吐量的最重要因素,并且在幼稚的解决方案中,它们使CPU停顿了很多。
rsp
包含b,而
esi
包含a;所以我们先做
edi
,然后做
b - a
-到目前为止很简单。
a - b
包含z,
eax
包含y。然后我们将b放入
edx
并向左移动一次(
ecx
)。
2 * b
是怎么回事?编译器实际上滥用CPU,以使其在单条指令中完成其余的计算,同时仍以最佳方式使用流水线和所有内容,并在尽可能多的CPU上分散工作负载(在我的CPU上,地址计算与“真正的” ALU)。令人印象深刻的一个例子,也许是一个例子,证明JITted代码实际上比实际的预编译代码可以更好地适应特定的CPU模型。当然,这些也是我们在手工组装中与较旧的硬件一起使用的技巧,但是……令人印象深刻。
关于c# - 调用方法时过多的汇编说明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36791544/
为了让我的代码几乎完全用 Jquery 编写,我想用 Jquery 重写 AJAX 调用。 这是从网页到 Tomcat servlet 的调用。 我目前情况的类似代码: var http = new
我想使用 JNI 从 Java 调用 C 函数。在 C 函数中,我想创建一个 JVM 并调用一些 Java 对象。当我尝试创建 JVM 时,JNI_CreateJavaVM 返回 -1。 所以,我想知
环顾四周,我发现从 HTML 调用 Javascript 函数的最佳方法是将函数本身放在 HTML 中,而不是外部 Javascript 文件。所以我一直在网上四处寻找,找到了一些简短的教程,我可以根
我有这个组件: import {Component} from 'angular2/core'; import {UserServices} from '../services/UserService
我正在尝试用 C 实现一个简单的 OpenSSL 客户端/服务器模型,并且对 BIO_* 调用的使用感到好奇,与原始 SSL_* 调用相比,它允许一些不错的功能。 我对此比较陌生,所以我可能会完全错误
我正在处理有关异步调用的难题: 一个 JQuery 函数在用户点击时执行,然后调用一个 php 文件来检查用户输入是否与数据库中已有的信息重叠。如果是这样,则应提示用户确认是否要继续或取消,如果他单击
我有以下类(class)。 public Task { public static Task getInstance(String taskName) { return new
嘿,我正在构建一个小游戏,我正在通过制作一个数字 vector 来创建关卡,该数字 vector 通过枚举与 1-4 种颜色相关联。问题是循环(在 Simon::loadChallenge 中)我将颜
我有一个java spring boot api(数据接收器),客户端调用它来保存一些数据。一旦我完成了数据的持久化,我想进行另一个 api 调用(应该处理持久化的数据 - 数据聚合器),它应该自行异
首先,这涉及桌面应用程序而不是 ASP .Net 应用程序。 我已经为我的项目添加了一个 Web 引用,并构建了各种数据对象,例如 PayerInfo、Address 和 CreditCard。但问题
我如何告诉 FAKE 编译 .fs文件使用 fsc ? 解释如何传递参数的奖励积分,如 -a和 -target:dll . 编辑:我应该澄清一下,我正在尝试在没有 MSBuild/xbuild/.sl
我使用下划线模板配置了一个简单的主干模型和 View 。两个单独的 API 使用完全相同的配置。 API 1 按预期工作。 要重现该问题,请注释掉 API 1 的 URL,并取消注释 API 2 的
我不确定什么是更好的做法或更现实的做法。我希望从头开始创建目录系统,但不确定最佳方法是什么。 我想我在需要显示信息时使用对象,例如 info.php?id=100。有这样的代码用于显示 Game.cl
from datetime import timedelta class A: def __abs__(self): return -self class B1(A):
我在操作此生命游戏示例代码中的数组时遇到问题。 情况: “生命游戏”是约翰·康威发明的一种细胞自动化技术。它由一个细胞网格组成,这些细胞可以根据数学规则生存/死亡/繁殖。该网格中的活细胞和死细胞通过
如果我像这样调用 read() 来读取文件: unsigned char buf[512]; memset(buf, 0, sizeof(unsigned char) * 512); int fd;
我用 C 编写了一个简单的服务器,并希望调用它的功能与调用其他 C 守护程序的功能相同(例如使用 ./ftpd start 调用它并使用 ./ftpd stop 关闭该实例)。显然我遇到的问题是我不知
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
我希望能够从 cmd 在我的 Windows 10 计算机上调用 python3。 我已重新安装 Python3.7 以确保选择“添加到路径”选项,但仍无法调用 python3 并使 CMD 启动 P
我是一名优秀的程序员,十分优秀!