效能優化總結(四) 預載入的設計

2021-09-23 21:41:48 字數 2891 閱讀 9548

本節說一下資料的預載入。這節的內容與sql沒什麼關係。主要說的是在 gix4專案 中,我們是如何設計符合需求的預載入類庫的。內容如下:

什麼是預載入,為什麼要用它?

我們所需要的api

乙個簡單的例子

什麼是預載入?

預載入其實就是在真正開始使用資料之前,先非同步把資料載入好,等到需要使用時,就可以直接使用之前載入好的資料。這時,由於資料已經載入完成,而不用等待漫長的載入過程,所以程式的速度得到乙個明顯的提公升。

那麼,什麼時候需要使用它呢?我覺得,主要是這種情況:當我們可以預知程式接下來的步驟中,很可能會用到一些資料,而獲取這些資料的操作比較耗時的時候,我們就可以使用預載入的方式,提前把資料準備好。

預載入需要使用非同步方法,也就是使用後台執行緒來載入資料。這樣做的好處當然是不會阻塞當前的主線程。(不過如果當前執行緒本身就是用於非同步載入資料的話,那就沒必要再新開執行緒了。)

我們可以使用很多種方式來實現非同步載入:在.net framework的類庫中,很多地方都提供了非同步程式設計模式(asynchronous programming design patterns)的api,使用這個模式,可以方便地實現各種非同步載入。當然,我們也可以使用2.0提供的threadpool.queueuserworkitem來實現一些輕量級的非同步操作。在.net4.0最新的api中,提供了task類來表示可執行任務。

但是,這些並不是我想要的api……

我們所需要的api

目前系統中預載入使用的場景需求是這樣的:

預載入可以對指定的資料獲取操作(loading action)進行封裝,在需要時呼叫。

使用資料的模組(使用者),並不一定知道是誰、在何時給它提前載入的資料。它只會申請使用資料。

發起非同步載入的模組(發起者),應該知道使用者是誰。

多個發起者之間沒有關係,但是都可以為某一使用者發起預載入。但是保證真正的資料載入操作,只會發生一次。

乙個類中,支援對它不同的資料進行不同載入方式,以方便按需載入。

從使用者的角度來看,不管有沒有發起者為它進行預載入,它都可以申請並拿到想要的資料。也就是說:

當沒有發起者為它進行預載入,那麼它的資料申請會導致即時的資料載入;

如果已經發起了預載入,而且資料已經載入完成,則直接獲取到載入好的資料;

如果資料沒有完成,則資料使用者需要等待資料的載入完成後,才可以獲取到資料並繼續當前的操作。

其中,最重要的就是最後點。

可以看到,這裡需要用到非同步操作、執行緒間同步。所以我們需要基於上面提到的多種api來實現,這裡我們使用的是簡單的執行緒池的方式,比較簡單,不再贅述。

最後設計出的api大致是這樣的:

public class

foreasyncloader

public event

eventhandler actionsucceeded;

/// ///

申請啟用執行緒進行預載入。

///

注意:///

本方法可以重入,多次呼叫也只會執行一次ladaction

///

public void beginloading();

/// ///

重設載入器。

///

使用此方法後,再次申請預載入時,會再次執行loadaction。

///

public void reset();

/// ///

等待資料載入完成。

///

public void waitforloading();

}}

例子
客戶程式使用時,需要為其定義乙個屬性,舉例如下:
資料持有者:
public class 

dataholder

}private object getdatafromweb()

}如果它的data1資料載入比較慢,我們可以為其定義乙個預載入屬性:

private 

foreasyncloader _dataloader;

/// ///

資料載入器

///

public

foreasyncloader dataloader

); }

return this._dataloader;

}}這樣,資料的「消費者」就可以使用這個資料:

public class 

dataconsumer

}

在這裡,雖然使用者並不知道有沒有其它**給holder執行了資料的預載入,但是當waitforloading方法執行完成後,資料是必然獲取到本地了。所以就可以直接使用資料。我們甚至可以把這句**放在data屬性的get**塊中,這樣,使用者甚至都不知道資料的獲取方案!
然後,可以在執行於它之前的**中,為這個「dataholder」申請預載入。例如,我們在應用程式啟動的時候,就開始預載入。下面的方法呼叫了beginloading方法,此方法會使用後台執行緒載入資料,所以這裡會立即返回:
public class 

invoker

}至此,就完成了乙個最簡單的預載入。

過程如下:
(圖畫得不熟,哪畫錯了,望大家指正,謝謝。)
小結
本篇主要說了一下在目前的系統中,如何設計出乙個滿足場景應用需求的預載入api。
預載入是乙個經常會被使用到的模式,希望對大家有用。

效能優化總結(四) 預載入的設計

本節說一下資料的預載入。這節的內容與sql沒什麼關係。主要說的是在 gix4專案 中,我們是如何設計符合需求的預載入類庫的。內容如下 什麼是預載入,為什麼要用它?我們所需要的api 乙個簡單的例子 什麼是預載入?預載入其實就是在真正開始使用資料之前,先非同步把資料載入好,等到需要使用時,就可以直接使...

前端效能優化 預載入

1.什麼是預載入 資源預載入是另乙個效能優化技術,我們可以使用該技術來預先告知瀏覽器某些資源可能在將來會被使用到。預載入簡單來說就是將所有所需的資源提前請求載入到本地,這樣後面在需要用到時就直接從快取取資源。2.為什麼要用預載入 在網頁全部載入之前,對一些主要內容進行載入,以提供給使用者更好的體驗,...

前端效能優化 資源預載入

預載入是瀏覽器對將來可能被使用資源的一種暗示,一些資源可以在當前頁面使用到,一些可能在將來的某些頁面中被使用。作為開發人員,我們比瀏覽器更加了解我們的應用,所以我們可以對我們的核心資源使用該技術。預載入可以拆分成很多小點 dns prefetch,subresource,prefetch,preco...