function call : called function call called function, call function stack, called function execution, call function out of the stack, call function continue to execute a seemingly simple process, the system bottom has done a lot of operations.
Operation:
1, call function frame pointer (function parameter, local variable, stack frame state value, function return address) into the stack, stack pointer self-subtraction
2, save the state data of the calling function into the register
3, the function frame pointer is called into the stack, the current called function is executed
4, the called function execution ends, the stack is returned to the calling function of the frame pointer, from the register to restore the current state data
5, continue to execute the calling function until the end
That is, the entire invocation operation has a compression stack out of the stack, saving and recovering the state data process. The system stack memory has a default intrinsic size. How many times the function call will allocate how many stack frames. Therefore, the function call performance impact has the following factors:
1, function recursive layer number;
2, number of parameters (the size of the memory that the parameter signature occupies)
2.1 The number of different parameters of the same type;
2.2 Parameter types with different number of parameters;
2.3 The same parameter number, but the parameter type is different from the memory size;
3, the function stack size, that is, the function of the local variables of the stack size.
To test the performance (time consuming) factor of the C function call, a simple program is written to run in the following environment:
Intel (R) Core (TM) i5-2400 CPU @ 3.10GHz memery size:7833700 KB (7.47GB)
At the beginning and end of the function call, use the clock () function in time.h to return the number of CPU clock ticks (StartTime and endtime in the table below), with durationtime=endtime-starttime representing the time consumption of the function call. As follows:
clock_t Starttime=clock ();
Function call ...
clock_t Endtime=clock ();
Divide by Clocks_per_sec to get the time result in seconds
double Durationtime= (double) (endtime-starttime)/clocks_per_sec;// indicates the time that the function call consumes the CPU. Time that does not include operations such as child processes or printf
Note: Clock () records the time the process consumes the CPU, the accuracy is milliseconds, and the address of the clock () function is explained in detail: http://site.douban.com/199048/widget/notes/12005386/note/253542964/
A function recursive layer number ( loop 1 million times )
Stack (bytes) |
Parameters (bytes) |
Recursion Count |
Total function call time consumption (seconds) |
Time consumption per loop function call (microseconds) |
Average time consumed per function call (nanoseconds) |
1024 |
24 |
10 |
2.9 |
2.9 |
290 |
1024 |
24 |
20 |
5.713 |
5.713 |
285.65 |
1024 |
24 |
30 |
9.025 |
9.025 |
300.83 |
1024 |
24 |
50 |
16.0767 |
16.0767 |
321.534 |
1024 |
24 |
80 |
21.79 |
21.79 |
272.375 |
1024 |
24 |
100 |
30.73 |
30.73 |
307.3 |
1024 |
24 |
200 |
66.24 |
66.24 |
331.2 |
Note: average per function call time consumption =durationtime/call layer/number of cycles
=durationtime/cycles per loop function call time
function calls are consumed on average at different times depending on the number of call layers, such as the following line chart:
Figure 1
The average time consumed for each function call, such as the following line chart:
Figure 2
Conclusion:1, the time consumption of function call increases with the increase of function call layer, when the parameter occupies the same memory and the function stack is the same size; 1;
2, in the case that the parameters occupy the same memory and the function stack is the same size, the time of each function call consumes about 300 nanoseconds; 2;
Second, the function stack size
Number of Cycles |
Stack (bytes) |
Parameters bytes |
Recursion Count |
Total function call time consumption (seconds) |
Time consumption per loop function call (microseconds) |
Average per function call (nanoseconds) |
1000000 |
16 |
24 |
50 |
9.4 |
9.4 |
184 |
1000000 |
32 |
24 |
50 |
9.37 |
9.37 |
187.4 |
1000000 |
64 |
24 |
50 |
9.5 |
9.5 |
190 |
1000000 |
128 |
24 |
50 |
10.415 |
10.415 |
208.3 |
1000000 |
256 |
24 |
50 |
11.805 |
11.805 |
236.1 |
1000000 |
512 |
24 |
50 |
14 |
14 |
280 |
1000000 |
1024 |
24 |
50 |
16.0767 |
16.0767 |
321.534 |
1000000 |
2048 |
24 |
50 |
18.42 |
18.42 |
368.4 |
Note: average per function call time consumption =durationtime/call layer/number of cycles
=durationtime/cycles per loop function call time
function calls are consumed on average at different times depending on the number of call layers, such as the following line chart:
Figure 3
The average time consumed for each function call, such as the following line chart:
Figure 4
Conclusion: 1, when the function parameter is the same asthe function call layer, the function call time consumption increases with the increment of function stack size; 3;
2, when the function parameter is the same as the function call layer, the time consumption of each function call increases with the increment of the function stack size; 4;
Three, the number of parameters
After the previous function tests, although there are errors, it is still possible to draw the effect of the parameters on the time consumption of the function call, which is the memory size of the parameters, there are two ways of the function parameter: The value of the parameter and the reference, and in the ordinary case, it will not consume too much memory; The effect of parameters on the time consumption of function calls is not obvious;
Iv.. Conclusion:
1, in the case that the function parameter size is 24 bytes and the function stack size is 1024 bytes, recursive 50 times the function time consumes 16.0767 microseconds, can roughly obtain each function call (stack out stack) time consumption of about 320 nanoseconds;
Ideas: 1, function parameter size: Function parameters are divided into values and reference parameters (parameter of the pointer), the general value of the parameter is a common value type, such parameters generally do not consume too much memory, the reference parameter is the parameter address does not consume too much memory, so in general, the function parameters on the function call time consumption has little effect;
2, Count: Cyclic 1 million function recursive, is to improve the accuracy of data and easy to calculate; 1 seconds =1000000 microseconds;
3, Recursive layer: Select the number of layers (24--35) that may be under normal recursion
4, function stack size: According to the Ethernet maximum byte 1500 bytes, choose to do the above experiments in 1024 bytes or so;
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define ARRAY_LEN 256
typedef struct {
int typeone;
int typetwo;
}struct_type;
Long call_back (int call_num,int typeone,int typetwo,int typethree,long P_recorde)
{
if (call_num<=0) return p_recorde;
int I_rand[array_len];
int i=0;
clock_t Start_time,end_time;
Start_time=clock ();
for (i=0;i<array_len;i++)
{
I_rand[i]=rand ();
}
End_time=clock ();
p_recorde+= (Long) (end_time-start_time);
Call_back (Call_num-1,typeone,typetwo,typethree,p_recorde);
}
void Main (int argc,char *argv[])
{
int Loop_num=atoi (argv[1]), Call_num=atoi (argv[2]);
Long p_recorde=0,sum=0;
clock_t Start_time,end_time;
Start_time=clock ();
int i;
for (i=0;i<loop_num;i++)
{
Sum_loop+=call_back (Call_num,0,0,0,p_recorde);
}
End_time=clock ();
Double Duration_time= (double) (end_time-start_time)/clocks_per_sec-(double) sum_loop/clocks_per_sec;
printf ("Sum=%f duration=%f\n", sum_loop,duration_time);
}
Code ideas: 1, in order to reduce the impact of the data cache hit, in each function call with Rand () to obtain a random number, and record time consumption A;
2, the total time consumption of recording function call B,b-a is the total time consumption of the function call;
Testing the performance factors of C-language function calls three