天天看點

java uuid第一次性能

在java中産生uuid的方式是使用java.util.UUID。

UUID.randomUUID().toString();

我在測試redis性能時,使用uuid産生測試資料,發現多線程測試redis的rpush接口的時候,性能老是上不去。 檢視cpu使用率也不高,網卡流量也不大。就是tps上不去。但是如果用兩台client去測,又可以達到更高的tps。

後來直接用jstack檢視了下堆棧,發現大多數線程停留在:

原來uuid的生成遇到了性能瓶頸。于是我單獨測試了下生成随機uuid的性能,發現無論是1個線程還是32個線程還是300個線程,它的tps隻能到10萬級别。 甚至是線程數越大,tps越低。tps在每個機器上都不一樣,有的機器上測試tps隻有5萬。我們就以一台雙核4G記憶體的虛拟機為例:

tps在 140000+

我們看randomUUID方法的javadoc的描述是: The UUID is generated using a cryptographically strong pseudo random number generator 也就是說uuid使用了一個強随機數,也也保證了uuid的不重複性。

再看SecureRandom的javadoc Note: Depending on the implementation, the generateSeed and nextBytes methods may block as entropy is being gathered, for example, if they need to read from /dev/random on various unix-like operating systems.

也就是說SecureRandom的nextBytes方法,依賴随機數的産生,如果随機數不夠了,它有可能就會堵塞在那邊。 比如随機數的産生是讀取unix類系統的/dev/random檔案。

我們再去看有關/dev/random的資訊:

Linux中的随機數可以從兩個特殊的檔案中産生,一個是/dev/urandom.另外一個是/dev/random。他們産生随機數的原理是利用目前系統的熵池來計算出固定一定數量的随機比特,然後将這些比特作為位元組流傳回。熵池就是目前系統的環境噪音,熵指的是一個系統的混亂程度,系統噪音可以通過很多參數來評估,如記憶體的使用,檔案的使用量,不同類型的程序數量等等。如果目前環境噪音變化的不是很劇烈或者目前環境噪音很小,比如剛開機的時候,而目前需要大量的随機比特,這時産生的随機數的随機效果就不是很好了。

這就是為什麼會有/dev/urandom和/dev/random這兩種不同的檔案,後者在不能産生新的随機數時會阻塞程式,而前者不會(ublock),當然産生的随機數效果就不太好了,這對加密解密這樣的應用來說就不是一種很好的選擇。/dev/random會阻塞目前的程式,直到根據熵池産生新的随機位元組之後才傳回,是以使用/dev/random比使用/dev/urandom産生大量随機數的速度要慢。

jdk預設的是讀取/dev/random檔案産生強随機數,但是如果不是為了産生加密随機數,我們可以設定jdk讀取/dev/urandom産生随機數,進而生成随機uuid。

在java啟動項中增加-Djava.security.egd=file:/dev/./urandom 配置項(不能寫作/dev/urandom,關于這個,網上有相關八卦曆史~)

再去相同的機器上測試uuid的性能:

tps在 720000+