2009年11月6日 星期五

memory copy效率比較

網路上看到的一篇文章
找個時間可以來try try看
說不定這個已經是舊文不再適用也說不定 :P

==========================================

Linux下面如果要把記憶體區塊由 A 拷貝到 B,我們除了可以使用memcpy來完成以外,還可以透過mmap來開啟檔案/proc/self/mem,來完成拷貝記憶體區塊的目的。

舉個例子來說,如果我們要把記憶體區塊由A拷貝到B chunksize bytes,可以透過如下的寫法

memcpy(B, A, chunksize);

透過mmap來做的話,可以藉由以下的寫法

int self;

self = open("/proc/self/mem", O_RDONLY);

B = mmap(B, chunksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, self, (off_t)A);

也就是透過Linux提供給每個Process的記憶體裝置檔案 mem,來完成記憶體的拷貝動作。

不過,雖然我們可以有這兩種方法可以選擇,可是遇到要拷貝記憶體時,卻不免會遇到要選擇何種方式來實做的問題,因此該網頁的作者寫了一個小程式來測試這兩種方式的優缺點,首先在Linux上每個記憶體的Page大小為512bytes,因此測試時就是利用 512 bytes為 單位來逐漸增加測試的記憶體區塊大小。每個階段都有一個固定的記憶體區塊大小,與兩個內容不同的記憶體區塊作為拷貝時的來源端,每一個循環都會先拷貝一個 來源端到目的的記憶體區塊中,再比較內容,若相同,則拷貝另一個來源端的資料到目的的記憶體區塊中,再比較內容,如此重複10000(表示共拷貝了20000次到目的記憶體區塊中),藉此來比較memcpymmap在執行記憶體區塊拷貝時的效率。

如下表

< 筆者電腦配備: PII 35064MB RAM>

memcpy

mmap

512

0.14

0.23

1024

0.26

0.35

2048

0.51

0.59

4096

1.00

1.06

8192

2.56

2.10

16384

5.67

4.55

32768

11.71

8.96

65536

23.63

17.75

我們不難發現當記憶體區塊為512102420484096時,memcpy都勝過mmap。不過當拷貝的記憶體區塊越來越大時,mmap明顯表現的相當有效率,像最後測試的記憶體區塊大小為65536 bytesmmap相較於memcpy所花的時間少了約6秒鐘。

由此我們可以了解到,如果在Linux上我們所撰寫的系統需要使用較大的記憶體區塊拷貝時,透過mmap來作或許是一個不錯的選擇。

http://loda.zhupiter.com/LinuxDynamicLibrary.htm

static library很佔flash size?

曾經聽到有人反應static library會很佔版子上的flash size
所以我想順便說明一下這中間的差別
假設分成三種case來看

1. 先不呼叫library提供的func,且當然也先不link
假設original code編好佔了約200KB

2. 一樣先不呼叫func,但在Makefile裡頭有加上-l *.a的部分
編好的ELF一樣是size不變的

3. 開始呼叫func,且作link
編好的ELF當然變大,但....size不會是等於200KB + *.a lib size
增加的部分當然只有你用到的func相關的code size
而不是整個static library size

另外
要注意的是
link是以object為單位
所以自己寫的library
最好是類似功能的,個別放單一個object
可不要通通寫成一個object
這樣就會將很多不必要的code通通link進來了

2009年11月3日 星期二

LGPL概略探討

LGPL的限制聽起來比GPL的鬆綁一些
但相信還是很多情況是讓人無所適從
所以這篇主要是作個筆記,記錄一下自己看到的一些看法

以下筆記來自:自由軟體鑄造場 林誠夏

=========================================
「自行編寫的程式與LGPL函式庫連接〈Link〉後,會不會與該函式庫結合〈Combine〉為一不可分割或很難分割的整體〈As a whole〉,而被認為整體皆為LGPL函式庫的衍生作品〈Derivative work),導致整個結合作品都要受到LGPL授權條款的拘束。」

所以、首先要探討的是,您自行編寫程式與此LGPL函式庫的調用/連結關係,行為上的判定是靜態連結〈Static link〉或是動態連結〈Dynamic link〉?

依照一般的通說,靜態連結指的是程式開啟時必然會開啟程式與該LGPL函式庫的連結關係,也就是說程式執行時對此LGPL函式庫有依賴性,若是少了這個函 式庫則整體程式幾乎沒有獨立的運作功能。在這種狀況之下,此個別編寫的程式與LGPL函式庫會被認為是一體程式,而需要整個專案都以LGPL授權的方式才 能再散布,在散布時也要提供「整個專案(自行編寫部份+LGPL函式庫)」的程式原始碼。

而若是您用dll般動態連結的方式來取用這個LGPL授權的函式庫,則表示該專案在開啟時並不會必然性的去取用/調用/連結LGPL函式庫的功能,只有在 需要某些特定功能時才去「動態式的呼叫」LGPL函式庫來得到資訊,這樣的狀況、若是除卻此一LGPL函式庫,但原來自行編寫的程式仍然具有可獨立運作的 基本功能的話,那可以視此程式與LGPL函式庫間僅為動態連結的存取關係,從而即使合併散布,但自行編寫的方式依自行律定的授權方式,而LGPL的部份則 依LGPL授權條款的方式散布,散布者原則上僅需提供LGPL函式庫部份的程式原始碼,以及該自行編寫程式與LGPL函式庫之間如何進行呼叫的 information exchange介面資訊即可。

====================================================
1、主程式啟動時直接啟動該LGPL函式庫的連結,這是靜態連結。

2、主程式啟動時並未啟動該LGPL函式庫的連結,僅在需求時才例外的呼叫LGPL的函式庫,例如一個多媒體檔案的播放程式,播放大部份媒體檔案時可以直接執行,但在播放某些特殊編碼的檔案時,才例外地去呼叫額外的LGPL函式庫來支援,這是動態連結。

所以上面的說法,常常又被簡化為:若除卻此LGPL函式庫,則主程式部份還具有基本功能者,為動態連結的利用結構;除卻此LGPL函式庫,則專案失卻主要功能者,為靜態連結的利用結構。

至於什麼才是「主要功能」或是「基本功能」,則解讀上更為見人見智。原則上必須要視個案來判定,舉個案來說,若釋出的載體是手機的話,手機的主要功能就是 撥打電話,若是除卻此一LGPL函式庫的連結造成電話無法撥打的話,那當然手機程式與此LGPL函式庫間是靜態連結的依賴關係;而若是此一LGPL函式庫 是電話簿的管理程式,若失去此一函式庫的連結,至不濟是電話簿的功能無法啟動,則「有可能」僅被判定為「動態連結」而不開啟LGPL授權條款的授權拘束 性,然而、這裡用的措詞只是「有可能」,實際上的狀況,還是要依個案來作進一步的分析。

=============================================================
我們同仁也曾經就LGPL使用Code的比例做過討論,我個人就這個議題查找的結果是,並沒有哪一個著名hacker會特別用程式碼的「比例」來判定「依賴性〈Dependency〉」。

其實LGPL授權條款裡有特別規定,原則上使用者不能去刪減該LGPL授權函式庫的功能,如果使用者主張只是單純使用這個函式庫的功能的話。

比方說您的程式只用到這個LGPL函式庫的a、b、c部份的功能,LGPL授權條款特別要求您在散布時,不要將函式庫本來有的d、e、f、g、h等功能刪 掉,LGPL授權條款向有保持該LGPL函式庫完整性的要求,因為就算您不用這些額外的功能,或許下一個得到該函式庫的使用者可能會想使用。

所以照「LGPL函式庫單純被使用原則上不能被刪改」的特性來說,該函式庫程式碼的比例會愈來愈高,這是LGPL授權預設機制所使然,在這樣的條件下,以程式碼的比例來判定依賴性也並不合理,所以從邏輯分析上、從授權者共識來說,應該都不會有這方面的問題