1. 程式人生 > >malloc動態申請記憶體空間對程式效率的影響

malloc動態申請記憶體空間對程式效率的影響

在程式設計時,為了節省空間,我們經常會呼叫malloc函式來動態申請空間。但是,卻不知道,正是因為這一點點的吝嗇心,讓我們的程式執行效率出奇的低。

那麼,引起效率低下的原因是什麼呢,接下來,讓我們探索探索。

探索一、

#include "stdafx.h"
#include <stdlib.h>
#include <time.h>

#define M 100
#define N 100
void TestMain(int n,int flag);
int _tmain(int argc, _TCHAR* argv[])
{
	clock_t start, end;
	start = clock();
	TestMain(10000000,1);
	end = clock();
	printf("The time was: %f\n", (double)(end - start) / CLK_TCK);
	start = clock();
	TestMain(10000000,2);
	end = clock();
	printf("The time was: %f\n", (double)(end - start) / CLK_TCK);
	return 0;
}

void MallocTest()
{
	int **dis = NULL;
	int i,j;
	dis = (int **)malloc((N + 1) * sizeof(int *));
	for (int i = 0; i <= N; ++i)
	{
		dis[i] = (int *)malloc((M + 1) * sizeof(int));
	}
	for (i = 1; i <= N; i++)
	{
		for (j = 1; j <= M; j++)
		{
			dis[i][j] = 1;
		}
	}

	for (int i = 0; i <= N; ++i)
	{
		free(dis[i]);
	}
	free(dis);
}

void ArryTest()
{
	int dis[N + 1][M + 1];
	int i,j;
	for (i = 1; i <= N; i++)
	{
		for (j = 1; j <= M; j++)
		{
			dis[i][j] = 1;
		}
	}
}

void TestMain(int n,int flag)
{
	if (flag == 1)
	{
		for (int i = 0; i < n; i++)
		{
			MallocTest();
			//ArryTest();
		}
	}
	else
	{
		for (int i = 0; i < n; i++)
		{
			//MallocTest();
			ArryTest();
		}
	}
}

執行結果:


從上面我們可以看到,MallocTest和ArryTest都申請了同樣大小的空間,並且進行了同樣的操作。在將它們同樣執行一千萬次以後,所用的時間:MallocTest為564.631s,ArryTest為232.96s,很明顯,因為malloc的使用,導致程式效率降低了一倍還多。

探索一中考慮的是二維陣列的情況,有人可能會說,二維陣列操作多了很多次迴圈,這多的操作步驟引起了程式效率的低下,那麼,當我們將維數降到一維的時候,情況又會怎樣呢?

探索二、

#include "stdafx.h"
#include <stdlib.h>
#include <time.h>

#define M 100
#define N 100
void TestMain(int n,int flag);
int _tmain(int argc, _TCHAR* argv[])
{
	clock_t start, end;
	start = clock();
	TestMain(100000000,1);
	end = clock();
	printf("The time was: %f\n", (double)(end - start) / CLK_TCK);
	start = clock();
	TestMain(100000000,2);
	end = clock();
	printf("The time was: %f\n", (double)(end - start) / CLK_TCK);
	return 0;
}

void MallocTest()
{
	int *dis = NULL;
	int i,j;
	dis = (int *)malloc((N + 1) * sizeof(int *));
	for (int i = 0; i <= N; ++i)
	{
		dis[i] = 1;
	}
	free(dis);
}

void ArryTest()
{
	int dis[N + 1];
	int i,j;
	for (i = 1; i <= N; i++)
	{
		dis[i] = 1;		
	}
}

void TestMain(int n,int flag)
{
	if (flag == 1)
	{
		for (int i = 0; i < n; i++)
		{
			MallocTest();
			//ArryTest();
		}
	}
	else
	{
		for (int i = 0; i < n; i++)
		{
			//MallocTest();
			ArryTest();
		}
	}
}

執行結果:


這是在一維的情況下對它們的測試結果,其中MallocTest和ArryTest均執行了一億次。很明顯,這次的差距也有兩倍多。。。

那麼,單變數的情況下,又會是什麼樣的結果呢?

探索三、

#include "stdafx.h"
#include <stdlib.h>
#include <time.h>

#define M 100
#define N 100
void TestMain(int n,int flag);
int _tmain(int argc, _TCHAR* argv[])
{
	clock_t start, end;
	start = clock();
	TestMain(100000000,1);
	end = clock();
	printf("The time was: %f\n", (double)(end - start) / CLK_TCK);
	start = clock();
	TestMain(100000000,2);
	end = clock();
	printf("The time was: %f\n", (double)(end - start) / CLK_TCK);
	return 0;
}

void MallocTest()
{
	int *dis = NULL;
	dis = (int *)malloc(sizeof(int));
	*dis = 1;
	free(dis);
}

void ArryTest()
{
	int dis;
	dis = 1;
}

void TestMain(int n,int flag)
{
	if (flag == 1)
	{
		for (int i = 0; i < n; i++)
		{
			MallocTest();
		}
	}
	else
	{
		for (int i = 0; i < n; i++)
		{
			ArryTest();
		}
	}
}

執行結果:


同樣上述兩個函式分別呼叫了一億次,結果差了好幾十倍呢。。

從以上幾個測試中,我們可以得出以下結論:

1、動態申請記憶體空間會影響程式效率;

2、當動態申請的空間越小時,對效率的影響越大。

那麼,為什麼會有這種差異呢?讓我們看看動態申請記憶體空間和採用臨時變數兩種情況的彙編程式碼吧。

int *dis = NULL;
	dis = (int *)malloc(sizeof(int));
	*dis = 1;
	free(dis);
上面這段程式碼的彙編程式碼為:
	int *dis = NULL;
012413AE  mov         dword ptr [dis],0  
	dis = (int *)malloc(sizeof(int));
012413B5  mov         esi,esp  
012413B7  push        4  
012413B9  call        dword ptr [__imp__malloc (12482B4h)]  
012413BF  add         esp,4  
012413C2  cmp         esi,esp  
012413C4  call        @ILT+310(__RTC_CheckEsp) (124113Bh)  
012413C9  mov         dword ptr [dis],eax  
	*dis = 1;
012413CC  mov         eax,dword ptr [dis]  
012413CF  mov         dword ptr [eax],1  
	free(dis);
012413D5  mov         esi,esp  
012413D7  mov         eax,dword ptr [dis]  
012413DA  push        eax  
012413DB  call        dword ptr [__imp__free (12482B8h)]  
012413E1  add         esp,4  
012413E4  cmp         esi,esp  
012413E6  call        @ILT+310(__RTC_CheckEsp) (124113Bh)  

而,下面的臨時變數的程式碼為:
int dis2;
	dis2 = 1;

它的彙編程式碼為:
int dis2;
	dis2 = 1;
012413EB  mov         dword ptr [dis2],1 

從彙編程式碼我們可以看出,使用malloc動態申請記憶體空間比採用臨時變數需要更多的彙編程式碼。多出這麼多彙編程式碼,機器程式碼多出多少,大家應該都能猜個大概吧。

綜上,給出以下建議:

當對記憶體空間消耗不是很大時,我們應該儘量使用臨時變數,這樣可以提高程式碼效率。當然,如果你的程式對記憶體大小要求相當嚴格,那就另當別論了。