背景
仍然是樹重建實驗,從點云里構(gòu)建鄰接圖是一個時間開銷比較大的步驟,對于幾千個數(shù)據(jù)點而言,一個O(N^2)的建圖過程大概會花幾秒左右,建圖屬于下圖中的 Initial Skeleton 步驟,然而我每次改動的代碼都在 Refinement 步驟里,也就是說,每次我點擊 Run 按鈕時,都要重復(fù)生成一模一樣的鄰居圖。

如果把生成的中間數(shù)據(jù)都緩存起來,重新Run 時直接讀取緩存,這樣就可以節(jié)省掉等待的時間了。
一開始的做法
我寫了一個接口,用來表示緩存數(shù)據(jù)的容器。
import java.io.Serializable;
/**
* T 類型的數(shù)據(jù)用于緩存!
* @param <T>
*/
public interface CachedData<T extends Serializable> {
T getData();
void setData(T s);
Class<T> getContentType();
boolean checkData();
}
我在實驗代碼使用 Spring IOC 容器來管理 Java Bean,每個實現(xiàn)了CachedData 接口的類會被我標(biāo)注為組件(@Component),寫 getData(),setData() 方法是為了在序列化和反序列化中讀取和注入數(shù)據(jù)。
聲明 getContentType() 是為了處理 Java 假泛型的問題,因為我需要在反序列化之后做類型檢查,不能因為緩存讀取錯誤就讓程序掛掉,但是這里的類型是T,泛型類型只能在編譯時獲取,無法在運行時獲取,我就寫這么一個方法在具體實現(xiàn)類里面給出 T 的類型信息。
讀 cache 的做法如下:
CachedData data = xxxx;
FileInputStream stream = new FileInputStream("xxxx.cache");
ObjectInputStream objStream = new ObjectInputStream(stream);
Serializable obj = (Serializable) objStream.readObject();
if (data.getContentType().isInstance(obj) {
data.setData(obj);
}
然后我就很歡喜地拿圖1里面的第二條數(shù)據(jù)進行測試,結(jié)果讓我大跌眼鏡,直接從 cache 文件里讀鄰接圖居然比在內(nèi)存里計算要慢!
后來就查了一下Java序列化相關(guān)的 東西, Java 序列化雖然會把二進制數(shù)據(jù)寫入文件,但是除了字段的值外,還會寫入其他的信息比如類信息(class),如果class引用了其他的class,就會存下這些數(shù)據(jù)。實際上Java的序列化和反序列化本身并不是很高效的操作。
如果使用JSON進行序列化呢?有空我要嘗試一下,據(jù)說比Serializable還要快一些。
其他的嘗試(20180515)
搜索了一下 Java 的高效序列化庫,看到了 kryo,Github上最新的版本是 4.0.2。這里把 Kryo 4.0.2,GSON 2.8.0,Oracle Java 8 Serializable 三者進行了對比,用比較學(xué)術(shù)的三線表展示一下對比結(jié)果:

第一列,操作說明:
- Load Data 是我的實驗代碼中從類 ply 格式的點云文件中讀取三維數(shù)據(jù)點操作。輸出 List<Point3d> 格式的數(shù)據(jù)。
- Build Octree 是求出點云的Bounding Box,然后對包圍盒遞歸劃分八叉樹,最后求出所有八叉樹格子。輸出 List<List<Point3d>> 格式的數(shù)據(jù)。
- Build 5-NN Graph,對數(shù)據(jù)點求5近鄰圖。輸出 HashMap<Long, HashMap<Long, Double> > 格式的數(shù)據(jù)。
- Extract Skeleton,求最短路徑圖,按測地距離決定結(jié)點先后順序,連接成初始骨架。輸出數(shù)據(jù)比較復(fù)雜。
這 4 個步驟都會輸出一些數(shù)據(jù),這個表就是對比 3 種序列化方法對輸出數(shù)據(jù)的反序列化性能。幾個步驟的數(shù)據(jù)大小不好衡量,我放出了 JSON 格式的數(shù)據(jù)大小(第六列)。
最后粗暴的對比結(jié)果就是:
Kryo 4.0.2 > GSON 2.8.0 > Oracle Java 8 Serializable