标签:
函数调用:即调用函数调用被调用函数,调用函数压栈,被调用函数执行,调用函数出栈,调用函数继续执行的一个看似简单的过程,系统底层却做了大量操作。
操作:
1, 调用函数帧指针(函数参数,局部变量,栈帧状态值,函数返回地址)入栈,栈指针自减
2, 保存调用函数的状态数据入寄存器
3, 被调用函数帧指针入栈,执行当前的被调用函数
4, 被调用函数执行结束,退栈,返回到调用函数的帧指针,从寄存器中恢复当时状态数据
5, 继续执行调用函数,直至结束
即整个调用操作有一个压栈出栈,保存和恢复状态数据的过程。而系统栈内存是有默认的固有大小。有多少次函数调用就会分配多少栈帧。故,函数调用性能影响有如下因素:
1,函数递归层数;
2,参数个数(参数签名所占内存大小)
2.1同类型不同参数个数;
2.2同参数个数不同参数类型;
2.3同参数类型同参数个数,但参数类型所占内存大小不同;
3,函数栈大小,即函数局部变量所占栈大小。
为了测试C语言函数调用性能(时间消耗)因素,编写了一个简单程序运行在如下环境中:
Windows7操作系统上的Vmware虚拟机中的ubuntu系统
在函数调用的开始与结束处,用time.h中的clock()函数返回CPU时钟计时单位数(下表中的starttime和endtime),用durationtime=endtime-starttime表示函数调用的时间消耗。如下:
clock_t starttime=clock();
函数调用…
clock_t endtime=clock();
//除以CLOCKS_PER_SEC,得到以秒为单位的时间结果
double durationtime=(double)(endtime-starttime)/CLOCKS_PER_SEC;
一.函数递归层数
递归层数
参数个数
函数栈大小
starttime
endtime
durationtime(秒)
10
5
1024
951
985
0.000034
10
5
1024
925
961
0.000036
10
5
1024
957
992
0.000035
20
5
1024
950
1004
0.000054
20
5
1024
897
952
0.000055
20
5
1024
996
1045
0.000049
30
5
1024
1075
1145
0.00007
30
5
1024
1031
1096
0.000065
30
5
1024
976
1040
0.000064
50
5
1024
1068
1167
0.000099
50
5
1024
1097
1196
0.000099
50
5
1024
1232
1331
0.000099
100
5
1024
940
1463
0.000523
100
5
1024
939
1113
0.000174
100
5
1024
938
1118
0.00018
100
5
1024
946
1144
0.000198
100
5
1024
968
1148
0.00018
500
5
1024
1033
2047
0.001014
500
5
1024
882
1983
0.001101
500
5
1024
801
1762
0.000961
500
5
1024
819
1842
0.001023
500
5
1024
859
1896
0.001037
1000
5
1024
983
3530
0.002547
1000
5
1024
936
3967
0.003031
1000
5
1024
917
3223
0.002306
1000
5
1024
1424
3500
0.002076
1000
5
1024
1008
3496
0.002488
1000
5
1024
963
3004
0.002041
1500
5
1024
763
4971
0.004208
1500
5
1024
903
7195
0.006292
1500
5
1024
1035
5375
0.00434
1500
5
1024
851
4375
0.003524
1500
5
1024
740
4002
0.003262
2000
5
1024
1065
5891
0.004826
2000
5
1024
1129
5701
0.004572
2000
5
1024
975
5019
0.004044
2000
5
1024
976
6288
0.005312
2000
5
1024
1017
7311
0.006294
3000
5
1024
762
11168
0.010406
3000
5
1024
832
8093
0.007261
3000
5
1024
1000
10505
0.009505
3000
5
1024
849
12248
0.011399
3000
5
1024
936
11466
0.01053
5000
5
1024
1144
18218
0.017074
5000
5
1024
1084
18654
0.01757
5000
5
1024
913
18257
0.017344
5000
5
1024
905
22046
0.021141
5000
5
1024
1043
18823
0.01778
6000
5
1024
847
29291
0.028444
6000
5
1024
824
21972
0.021148
6000
5
1024
743
20547
0.019804
6000
5
1024
890
19888
0.018998
6000
5
1024
810
19193
0.018383
7000
5
1024
962
23460
0.022498
7000
5
1024
1040
21367
0.020327
7000
5
1024
986
20902
0.019916
7000
5
1024
1017
24210
0.023193
7000
5
1024
977
21932
0.020955
上表测试平均值如下:
递归层数
参数个数
函数栈大小
Avrg_durationtime(微秒)[平均值]
每次递归平均值(微秒)
10
5
1024
35
3.5
20
5
1024
52.66
2.633
30
5
1024
66.33
2.211
50
5
1024
99
1.98
100
5
1024
251
2.51
500
5
1024
1027.2
2.0544
1000
5
1024
2414.83
2.414
1500
5
1024
4325.2
2.883
2000
5
1024
5009.6
2.5048
3000
5
1024
9820.2
3.2734
5000
5
1024
18181.8
3.63636
6000
5
1024
21355.4
3.5592
7000
5
1024
21377.8
3.0597
根据平均值表绘折线图如下:(系统在递归层数超过7000会栈溢出)
在同函数参数个数同函数栈大小的情况下,每次函数调用平均时间消耗图:
二.参数个数
递归层数
参数个数
函数栈大小
starttime
endtime
durationtime(秒)
2000
1
1024
904
8318
0.007414
2000
1
1024
982
8508
0.007526
2000
1
1024
968
8361
0.007393
2000
1
1024
1212
8101
0.006889
2000
1
1024
1269
5964
0.004695
2000
1
1024
906
9532
0.008626
2000
1
1024
786
8110
0.007324
2000
1
1024
929
7708
0.006779
2000
1
1024
895
7900
0.007005
2000
1
1024
959
4732
0.003773
2000
3
1024
1569
9858
0.008289
2000
3
1024
999
6132
0.005133
2000
3
1024
1083
6673
0.00559
2000
3
1024
1170
8269
0.007099
2000
3
1024
946
5683
0.004737
2000
3
1024
846
6908
0.006062
2000
3
1024
828
7849
0.007021
2000
3
1024
977
7079
0.006102
2000
3
1024
845
8521
0.007676
2000
3
1024
1047
8368
0.007321
2000
5
1024
911
7754
0.006843
2000
5
1024
1173
5677
0.004504
2000
5
1024
1477
12230
0.010753
2000
5
1024
908
5397
0.004489
2000
5
1024
988
10145
0.009157
2000
5
1024
759
8113
0.007354
2000
5
1024
885
8954
0.008069
2000
5
1024
917
6160
0.005243
2000
5
1024
831
6685
0.005854
2000
5
1024
900
7814
0.006914
2000
10
1024
1359
6479
0.00512
2000
10
1024
1678
7318
0.00564
2000
10
1024
1956
9234
0.007278
2000
10
1024
964
8546
0.007582
2000
10
1024
939
6501
0.005562
2000
10
1024
829
7508
0.006679
2000
10
1024
891
8894
0.008003
2000
10
1024
877
7126
0.006249
2000
10
1024
930
6761
0.005831
2000
10
1024
920
7762
0.006842
上表测试平均值如下:
递归层数
参数个数
函数栈大小
Avrg_durationtime(微秒)[平均值]
每次递归平均值(微秒)
2000
1
1024
6742.4
3.3712
2000
3
1024
6503
1.0838*3=3.2514
2000
5
1024
6918
0.6918*5=3.459
2000
10
1024
6478.6
0.32393*10=3.2393
根据平均值表绘折线图如下:
每个参数每次递归平均值折线图:
结论:在同函数栈大小和同递归层数的情况下,函数参数个数没造成规模性差异的时候,平均时间消耗几乎相近。
三.函数栈大小
递归层数
参数个数
函数栈大小
starttime
endtime
durationtime(秒)
2000
5
1024
1242
10890
0.009648
2000
5
1024
1337
14279
0.012942
2000
5
1024
1069
8970
0.007901
2000
5
1024
1023
12279
0.011256
2000
5
1024
970
8142
0.007172
2000
5
2048
1177
14290
0.013113
2000
5
2048
984
16388
0.015404
2000
5
2048
1051
12327
0.01276
2000
5
2048
899
15451
0.014552
2000
5
2048
1372
14674
0.013302
2000
5
3072
1238
15792
0.014554
2000
5
3072
914
13615
0.012701
2000
5
3072
1406
17867
0.016461
2000
5
3072
978
17876
0.016898
2000
5
3072
1008
16438
0.01543
2000
5
4096
1242
10890
0.009648
2000
5
4096
1337
14279
0.012942
2000
5
4096
1069
8970
0.007901
2000
5
4096
1023
12279
0.011256
2000
5
4096
970
8142
0.007172
上表测试平均值如下:
递归层数
参数个数
函数栈大(int)
Avrg_durationtime(微秒)[平均值]
每个参数每次递归平均值(微秒)
2000
5
1024
5009.6
2.5048/5=0.50096
2000
5
2048
9783.8
4.8919/5=0.97838
2000
5
3072
13826.2
6.9131/5=1.38262
2000
5
4096
15208.8
7.6044/5=1.52088
根据平均值表绘折线图如下:(函数栈大小超过5120会栈溢出)
每个参数每次递归平均值折线图:
结论:单个函数参数单词函数调用所需要的时间消耗与函数栈大小几乎成对等倍数增长。
四.结论
1,在函数参数和函数栈大小一定时,函数递归调用的时间消耗在一定递归层数范围内与递归层数呈现正相关关系。
2,在函数递归层数和函数参数个数一定时,函数递归调用的时间消耗在一定函数栈大小范围内与函数栈大小呈现正相关关系。
3,在函数参数个数没有造成规模性差异的情况下(即函数签名所占栈内存不大时),函数参数个数所造成的时间消耗几乎相近。
4,在函数参数个数没有造成规模性差异的情况下(即函数签名所占栈内存不大时),函数调用层数和函数栈大小对函数调用的时间消耗产生明显影响。
注:1,由于程序测试的操作系统环境的差异,可能会导致数据误差。
2,计时方法的差异,可能会导致数据误差。
3,个人编码能力也可能导致数据误差。
标签: