日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

通过快速Java和文件序列化加快速度

發(fā)布時(shí)間:2023/12/3 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 通过快速Java和文件序列化加快速度 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

從Java的第一個(gè)版本開(kāi)始,每天都有許多開(kāi)發(fā)人員試圖至少達(dá)到與C / C ++一樣好的性能。 JVM供應(yīng)商正在通過(guò)實(shí)現(xiàn)一些新的JIT算法來(lái)盡力而為,但仍有許多工作要做,尤其是在我們?nèi)绾问褂肑ava方面。

例如,對(duì)象<->文件序列化有很多優(yōu)勢(shì),尤其是在易于存儲(chǔ)的對(duì)象的讀寫(xiě)中。 我將嘗試闡明該主題。

所有測(cè)試都在下面顯示的簡(jiǎn)單對(duì)象上執(zhí)行:

public class TestObject implements Serializable {private long longVariable;private long[] longArray;private String stringObject;private String secondStringObject; //just for testing nulls/* getters and setters */ }

為了更簡(jiǎn)潔,我將僅顯示write方法(盡管另一種方法也非常相似)。 完整的源代碼可在我的GitHub(http://github.com/jkubrynski/serialization-tests)上找到。

最標(biāo)準(zhǔn)的Java序列化(我們都從這里開(kāi)始)如下所示:

public void testWriteBuffered(TestObject test, String fileName) throws IOException {ObjectOutputStream objectOutputStream = null;try {FileOutputStream fos = new FileOutputStream(fileName);BufferedOutputStream bos = new BufferedOutputStream(fos);objectOutputStream = new ObjectOutputStream(bos);objectOutputStream.writeObject(test);} finally {if (objectOutputStream != null) {objectOutputStream.close();}} }

加快標(biāo)準(zhǔn)序列化的最簡(jiǎn)單方法是使用RandomAccessFile對(duì)象:

public void testWriteBuffered(TestObject test, String fileName) throws IOException {ObjectOutputStream objectOutputStream = null;try {RandomAccessFile raf = new RandomAccessFile(fileName, "rw");FileOutputStream fos = new FileOutputStream(raf.getFD());objectOutputStream = new ObjectOutputStream(fos);objectOutputStream.writeObject(test);} finally {if (objectOutputStream != null) {objectOutputStream.close();} }

更復(fù)雜的技術(shù)是使用Kryo框架。 新舊版本之間的差異很大。 我都檢查了。 因?yàn)樾阅鼙容^沒(méi)有發(fā)現(xiàn)任何明顯的不同,所以我將重點(diǎn)介紹第二個(gè)版本,因?yàn)樗佑脩粲押?#xff0c;甚至更快。

private static Kryo kryo = new Kryo(); // version 2.xpublic void testWriteBuffered(TestObject test, String fileName) throws IOException {Output output = null;try {RandomAccessFile raf = new RandomAccessFile(fileName, "rw");output = new Output(new FileOutputStream(raf.getFD()), MAX_BUFFER_SIZE);kryo.writeObject(output, test);} finally {if (output != null) {output.close();}} }

最后一個(gè)選擇是受Martin Thompson文章啟發(fā)的解決方案。 它顯示了如何以C ++方式和Java處理內(nèi)存

public void testWriteBuffered(TestObject test, String fileName) throws IOException {RandomAccessFile raf = null;try {MemoryBuffer memoryBuffer = new MemoryBuffer(MAX_BUFFER_SIZE);raf = new RandomAccessFile(fileName, "rw");test.write(memoryBuffer);raf.write(memoryBuffer.getBuffer());} catch (IOException e) {if (raf != null) {raf.close();}} }

TestObject的寫(xiě)入方法如下所示:

public void write(MemoryBuffer unsafeBuffer) {unsafeBuffer.putLong(longVariable);unsafeBuffer.putLongArray(longArray);// we support nullsboolean objectExists = stringObject != null;unsafeBuffer.putBoolean(objectExists);if (objectExists) {unsafeBuffer.putCharArray(stringObject.toCharArray());}objectExists = secondStringObject != null;unsafeBuffer.putBoolean(objectExists);if (objectExists) {unsafeBuffer.putCharArray(secondStringObject.toCharArray());} }

直接內(nèi)存緩沖區(qū)類(簡(jiǎn)稱,只是為了展示這個(gè)主意):

public class MemoryBuffer {// getting Unsafe by reflectionpublic static final Unsafe unsafe = UnsafeUtil.getUnsafe();private final byte[] buffer;private static final long byteArrayOffset = unsafe.arrayBaseOffset(byte[].class);private static final long longArrayOffset = unsafe.arrayBaseOffset(long[].class);// other offsets private static final int SIZE_OF_LONG = 8;// other sizes private long pos = 0;public MemoryBuffer(int bufferSize) {this.buffer = new byte[bufferSize];}public final byte[] getBuffer() {return buffer;}public final void putLong(long value) {unsafe.putLong(buffer, byteArrayOffset + pos, value);pos += SIZE_OF_LONG;}public final long getLong() {long result = unsafe.getLong(buffer, byteArrayOffset + pos);pos += SIZE_OF_LONG;return result;}public final void putLongArray(final long[] values) {putInt(values.length);long bytesToCopy = values.length << 3;unsafe.copyMemory(values, longArrayOffset, buffer, byteArrayOffset + pos, bytesToCopy);pos += bytesToCopy;}public final long[] getLongArray() {int arraySize = getInt();long[] values = new long[arraySize];long bytesToCopy = values.length << 3;unsafe.copyMemory(buffer, byteArrayOffset + pos, values, longArrayOffset, bytesToCopy);pos += bytesToCopy;return values;}/* other methods */ }

卡尺運(yùn)行多個(gè)小時(shí)的結(jié)果如下所示:

全程旅行[ns] 標(biāo)準(zhǔn)偏差[ns]
標(biāo)準(zhǔn) 207307 2362
英國(guó)皇家空軍的標(biāo)準(zhǔn) 42661 733
KRYO 1.x 12027 112
KRYO 2.x 11479 259
不安全 8554 91

最后我們可以得出一些結(jié)論:

  • 不安全的序列化比java.io.Serializable的標(biāo)準(zhǔn)用法快23倍以上
  • 使用RandomAccessFile可以將標(biāo)準(zhǔn)緩沖序列化速度提高近4倍
  • Kryo動(dòng)態(tài)序列化比手工實(shí)現(xiàn)的直接緩沖區(qū)慢約35%。

最后,我們可以看到,仍然沒(méi)有金錘。 對(duì)于我們很多人來(lái)說(shuō),獲得3000 ns(0.003ms)的值不值得為我們要與文件序列化的每個(gè)對(duì)象編寫(xiě)自定義實(shí)現(xiàn)。 對(duì)于標(biāo)準(zhǔn)解決方案,我們主要選擇Kryo。 然而,在低延遲系統(tǒng)中,100ns似乎是永恒的,選擇將完全不同。

參考:來(lái)自Java(B)Log博客的JCG合作伙伴 Jakub Kubrynski的快速Java和文件序列化加速。

翻譯自: https://www.javacodegeeks.com/2013/09/speed-up-with-fast-java-and-file-serialization.html

總結(jié)

以上是生活随笔為你收集整理的通过快速Java和文件序列化加快速度的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。