1.参数入栈,将函数参数入栈,这是现在函数调用的标准方式。所以参数越多,开销越大
2.将控制权转移至函数中.
3.建立新的栈帧,也就是当前函数使用的“一片”栈空间,使用ebp的值来标识新的栈帧,因此要将原栈帧首地址保存下来,方便回到原来的即调用者的栈帧。
4.恢复原栈帧,然后将控制权转移至调用者.
- 普通函数
C/C++ 普通函数的开销包括函数调用、参数传递、局部变量的创建和销毁等。
其中函数调用是最主要的开销,因为每次函数调用都需要保存当前函数的返回地址和上下文信息,然后跳转到被调用函数的代码段执行,最后再返回到调用函数的代码段继续执行。
这个过程会涉及到栈的操作,所以栈的使用也是C/C++普通函数开销的一部分。
- 模板函数
模板函数需要在编译时进行实例化,会增加内存消耗,调用时开销与普通函数一致
- 内联 、宏函数
宏函数是在编译时展开的,因此没有函数调用的开销,但是它可能会导致代码膨胀和可读性差的问题。
内联函数则是在编译时将函数体嵌入到调用处,因此也没有函数调用的开销,但是它需要编译器支持,并且可能会导致代码膨胀和代码重复的问题。
因此,在使用内联函数和宏函数时需要根据具体情况进行选择。
- 虚函数
C++虚函数运行时调用的额外开销产生于虚函数表的查找和函数指针的间接调用。
因此不同函数的开销对比:内联 、宏函数< 普通函数、模板函数 < 虚函数
Linux 系统调用的开销通常比普通函数的开销要高几倍,因为系统调用需要从用户态切换到内核态,这个过程需要进行一些额外的操作,比如保存和恢复 CPU 寄存器、切换内存地址空间等。
- 系统调用虽然使用了“快速系统调用”指令,但耗时仍大约在200ns+,多的可能到十几us
- 每个系统调用内核要进行许多工作,大约需要执行1000条左右的CPU指令
“time a simple command or give resource usage”,
即测量命令的执行时间,或者给出系统资源的使用情况。
#如果你想查看一条命令(比如 ls)到底执行了多长时间,我们可以这样做:
[roc@linux ~]$ time lsprogram public_html repo rocscm
real 0m0.002s
user 0m0.002s
sys 0m0.000s
(1)
real:从进程 ls 开始执行到完成所耗费的 CPU 总时间。该时间包括 ls 进程执行时实际使用的 CPU 时间,ls 进程耗费在阻塞上的时间(如等待完成 I/O 操作)和其他进程所耗费的时间(Linux 是多进程系统,ls 在执行过程中,可能会有别的进程抢占 CPU)。
(2)user:进程 ls 执行用户态代码所耗费的 CPU 时间。该时间仅指 ls 进程执行时实际使用的 CPU 时间,而不包括其他进程所使用的时间和本进程阻塞的时间。
(3)sys:进程 ls 在内核态运行所耗费的 CPU 时间,即执行内核系统调用所耗费的 CPU 时间。
说明:单核处理器:real_time≥ (user_time+sys_time),多核则不一定。