啟動優化之動態庫延遲載入

卡哥發表於2018-12-10

程式啟動過程中載入過多動態庫會導致啟動變慢,尤其是剛開機時啟動程式,載入過多的dll會佔用IO,這時候系統IO通常是非常繁忙的,會拖慢啟動速度。

        動態庫載入包括靜態載入和動態載入, 靜態載入就是使用lib,程式碼生成過程中連結用的。靜態載入可以使用動態庫中的匯出函式和匯出類,但是靜態載入是程式啟動時載入動態庫,會佔用啟動時間。動態載入用LoadLibrary函式載入動態庫,可以隨時動態載入DLL,不需要lib,不需要在啟動時載入可以節省啟動時間。但是隻能用GetProcAddress獲取匯出函式,對匯出類通常是無能為力的,相對來說GetProcAddress使用也沒有靜態載入方便。

        動態庫延遲載入可以解決上述缺點,既可以不在啟動時載入,不佔用啟動時間,也不需要GetProcAddress獲取匯出函式,可以直接使用匯出函式和匯出類(尤其是第三方DLL只提供匯出類的情況下)。總體來說即靈活快速,又方便使用。

        動態庫延遲載入節省了啟動時間,也節省了系統資源,剛開機時IO慢時不進行載入,到後面IO不忙的時候載入DLL就會快很多,所以延遲載入並不一定造成後面模組使用時卡頓。

延遲載入設定:

在vs專案屬性--配置屬性--連結器--輸入--延遲載入的DLL中設定需要延遲載入的DLL,可以設定多個,用分號隔開。
在vs專案屬性--配置屬性--連結器--輸入--附加依賴項 填寫DLL對應的lib,或者程式碼中用#pragma comment( lib,"..\\Lib\\LiveStreamTrans.lib" ) 來載入lib,這裡只需要延遲載入的DLL的lib,DLL依賴的但又沒有在專案中直接使用的其他DLL的lib不需要。
在程式碼中手動載入DLL,如果有多個DLL,需要包含DLL的依賴DLL,並且要按依賴順序載入,被依賴的先載入,載入使用LoadLibrary函式,如果不按依賴順序載入會導致LoadLibrary失敗。
要注意控制載入時機,DLL函式或者類的使用不能早於該DLL被LoadLibrary,通常如果是懶載入方式,是該功能模組使用時載入,這樣比較節省資源;
載入相同動態庫不要載入多次,外部可以用靜態變數判斷一下是否載入過。
示例程式碼如下:

void LiveFuncMgr::LoadAudioDll()
{
	LOGI("{}", __FUNCTION__);
 
	static const vector<wstring> delay_load_dlls = {
			L"w32-pthreads.dll",
 
			L"postproc-55.dll",
			L"swresample-3.dll",
			L"swscale-5.dll",
			L"avcodec-58.dll",
			L"avdevice-58.dll",
			L"avfilter-7.dll",
			L"avformat-58.dll",
			L"avutil-56.dll",
 
			L"libfaac.dll",
			L"libfaad2.dll",
			L"libglog.dll",
			L"libogg.dll",
			L"libspeex.dll",
			L"libspeexdsp.dll",
			L"AudioLive.dll"
			//L"LiveStreamTrans.dll"
	};
 
	std::wstring wstrDir = util::get_exe_dirw() + L"Plugins\\Live\\deps\\";
 
	for (size_t i = 0; i < delay_load_dlls.size(); ++i)
	{
		util::load_library((wstrDir + delay_load_dlls[i]).c_str());
	}
}
 
void Init()
{
	static bool s_dll_loaded = false;
	if (!s_dll_loaded)
	{
		LiveFuncMgr::GetInstance()->LoadAudioDll();
		s_dll_loaded = true;
	}
}
 

 

相關文章