所謂的熱點圖,是圖1)構建一張灰度圖,圖2)在每一個熱點的位置上繪製併疊加造成灰色的熱點圖,圖3)根據顏色表生成熱點圖。不難看出,最核心的是圖2的過程。詳情參考《可視化之熱點圖》。 算法
圖1 併發
圖2&圖3 性能
這種思路效率高,缺點就是不夠靈活,每一個點都是同一個樣式,沒有考慮該點的半徑和權重。建立大小不一的模版(章),每一個熱點根據本身的半徑值選擇對應的章就能夠,實現思路以下: 測試
半徑&模版 大數據
權重的不一樣,是經過蓋章的「力度」,權重越大,不透明度越大,這樣疊加時也越能體現權重大的效果。是否發現,這個方式會產生覆蓋狀況,並不嚴謹。 優化
權重&透明度(力度) 設計
咱們看看在不一樣數據量下的性能分析。7759個熱點,每一個點有經緯度和權重三個float值,生成一張2000*1400左右的熱點圖。採用pa7/heatmap.js,在Chrome下測試1w(1倍),5w(5倍),10w(15倍),60w(75倍),100w(150倍),600w(750)六個級別,千萬級別會崩潰。3d
備註:只測試了一次,偏差估計不小,僅供參考。blog
數據轉換消耗(毫秒) 索引
純渲染時間(毫秒)
在這種方式下渲染時間依次爲:68,100,194,894,2918,63817(ms)。數據量在100w之內的還好,渲染時間將近3s。但再往上就不給力了。千萬級別下讀取會崩潰,內存達到1.2G以上。渲染就算可用,從時間消耗上也不實用。
在渲染性能方面,以前咱們經過模版,蓋章的思路已經優化了,沿着這個思路提高空間不大。並且,由於渲染上存在疊加依賴,很難並行。
本身實現渲染算法,以並行的方式實現數值計算部分。思路以下:對熱點圖這個目標圖片,遍歷每個像素,以像素半徑作一個緩衝區分析,獲取對應的熱點數據(數據支持範圍查詢)。若是沒有熱點,則該像素爲空;若是存在N個熱點,則計算該點的熱點值。乍看上去,這不是又倒退到逐點計算的思路上。
坦白說,我很不喜歡這個思路,就比如老師出了一道1+2+3……+100的題目,原本是想讓你發現規律和數據模型,。但是你真的在一個個累加。但全班同窗合做,把這100個數分解成10組,每人分別計算一部分,一樣也能很快得出結果,這就是另外一個角度的智慧。
由於每一個點的計算是獨立的,能夠經過並行來優化「渲染」時間。但這種思路是以放棄渲染技術爲代價的,也要藉助於空間索引,並行計算,在JS上很難實現。
另外,這個思路讓我認爲(不知道對不對),點差值和熱點圖並沒有本質區別。
下圖是OpenGL的思路:每個熱點構形成一個正方形,對角線將其分爲兩個三角形,有四個頂點和6個頂點索引。採用批次渲染的方式,每一個批次下渲染1w個熱點(對應4w個頂點),將數據分解爲多個批次,實現大數據的渲染,GPU中實現混合效果。具體的shader代碼能夠參考pyalot。
我在WebGL下實現了這個思路,仍是剛纔那個7759個熱點的數據,我放到一個渲染批次,對這一個批次渲染屢次, 1s內完成千萬級別的渲染。
數據解析是瓶頸,好比經緯度點最終要轉換到像素單。若是性能還不夠,就「偷工減料」,創建矢量金字塔,本質就是把N個點合併成一個,減小渲染過程的計算量。
二維對應的策略是,渲染性能不夠,就把渲染問題轉爲for循環下的簡單計算,而後經過CPU並行優化;對於三維,須要點轉三角形,建立buffer,而後經過GPU實現渲染過程。
從渲染的角度來看,不管二維仍是三維,在十萬級別下的性能都不錯,百萬級別也能接受,差異不大,但十萬以上,二者的渲染差距則體現出來,前者像打狗棒,強調的是心法和招式,後者則是降龍十八掌,靠的是內力。兩點區別,二維是由於渲染性能不行,只好採用最簡單的數值計算,以這樣的代價實現核心計算的並行;三維自己就是並行策略,就是經過shader,經過頂點和片元實現GPU的並行。第二,GPU的並行能力顯然不是CPU能夠媲美的,換句話說,GPU可以承擔更多的併發計算量,儘量少的對原始數據作預處理,理論上,只要內存夠用或讀取數據合理,顯存上經過批次渲染,能夠渲染任意大的數據量,並且時間和批次應該是線性的。
v最後,再強調一下數據。簡單計算了一下,假如是一個二進制流的方式,一個熱點佔12個字節,這樣1kw個點要佔120M,即便壓縮後也得20M,這尚未考慮數據轉換上的消耗。對於Web端,基於原始數據,須要有一種機制,可以快速的完成數據傳輸和處理。
有一個不必定對的思路,建一個GeoHash,大範圍的預先生成熱點圖,更新頻率能夠不高;局部範圍則經過GeoHash獲取對應的熱點,實現本地渲染。GeoHsh貌似是一種很不錯的大數據設計方式,我也不太瞭解,有時間z再研究研究。
還有一個收穫,當複雜度達到必定程度,原先行得通的算法和方案不必定知足要求了。更精彩的是,由於性能低,之前認爲比較差的思路,由於思路簡單,容易實現並行改造,居然可行了。