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

从Java的第一个版本开始,每天都有许多开发人员试图至少达到与C / C ++一样好的性能。 JVM供应商正在通过实现一些新的JIT算法来尽力而为,但仍有许多工作要做,尤其是在我们如何使用Java方面。

例如,对象<->文件序列化有很多优势,尤其是在易于存储的对象的读写中。 我将尝试阐明该主题。

所有测试都在下面显示的简单对象上执行:

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

为了更简洁,我将仅显示write方法(尽管另一种方法也非常相似)。 完整的源代码可在我的GitHub(http://github.com/jkubrynski/serialization-tests)上找到。

最标准的Java序列化(我们都从这里开始)如下所示:

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();}}
}

加快标准序列化的最简单方法是使用RandomAccessFile对象:

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();}      
}

更复杂的技术是使用Kryo框架。 新旧版本之间的差异很大。 我都检查了。 因为性能比较没有发现任何明显的不同,所以我将重点介绍第二个版本,因为它更加用户友好,甚至更快。

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();}}
}

最后一个选择是受Martin Thompson文章启发的解决方案。 它显示了如何以C ++方式和Java处理内存

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的写入方法如下所示:

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());}
}

直接内存缓冲区类(简称,只是为了展示这个主意):

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 */
}

卡尺运行多个小时的结果如下所示:

全程旅行[ns] 标准偏差[ns]
标准 207307 2362
英国皇家空军的标准 42661 733
KRYO 1.x 12027 112
KRYO 2.x 11479 259
不安全 8554 91

最后我们可以得出一些结论:

  • 不安全的序列化比java.io.Serializable的标准用法快23倍以上
  • 使用RandomAccessFile可以将标准缓冲序列化速度提高近4倍
  • Kryo动态序列化比手工实现的直接缓冲区慢约35%。

最后,我们可以看到,仍然没有金锤。 对于我们很多人来说,获得3000 ns(0.003ms)的值不值得为我们要与文件序列化的每个对象编写自定义实现。 对于标准解决方案,我们主要选择Kryo。 然而,在低延迟系统中,100ns似乎是永恒的,选择将完全不同。

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367037.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flask mysql 模版传参_Flask渲染Jinja2模板和传参

### Flask渲染Jinja2模板和传参&#xff1a;1. 如何渲染模板&#xff1a;* 模板放在templates文件夹下* 从flask中导入render_template函数。* 在视图函数中&#xff0c;使用render_template函数&#xff0c;渲染模板。注意&#xff1a;只需要填写模板的名字&#xff0c;不需要…

08 Spring框架 AOP (一)

首先我们先来介绍一下AOP&#xff1a; AOP&#xff08;Aspect Orient Programming&#xff09;&#xff0c;面向切面编程&#xff0c;是面向对象编程OOP的一种补充。 面向对象编程是从静态角度考虑程序的结构&#xff0c;面向切面编程是从动态的角度考虑程序运行过程。 AOP底层…

使用Spring 3.2的DeferredResult进行长轮询

在我们的最后一集中 &#xff0c; Agile Cowboys Inc.的首席执行官刚刚雇用了Java / Spring顾问&#xff0c;方法是为他提供最初为女友购买的保时捷。 这位首席执行官的女友因失去保时捷而感到不安&#xff0c;已将其婚外情告诉了他的妻子。 他的妻子在分拆了CEO的套房后已申请…

移动spa商城优化记(一)---首屏优化篇

背景 随着公司业务的不断壮大&#xff0c;最近老是有用户反应公司APP内的商城打开比较慢&#xff0c;这可不行啊&#xff0c;慢了容易流失用户&#xff0c;流失用户减少公司业绩&#xff0c;公司业绩少我的年终奖就少…………&#xff0c;所以为了公司&#xff0c;也为了自己&a…

hprose for java 教程_hprose for java源码分析-4

4.1 疑窦丛生书接上回。上回说到&#xff0c;从HproseClient.java ------------------------- (#0)invokeHandler.handle()开始&#xff0c;将经历一个漫长的调用过程&#xff0c;下面把整个调用链粘出来&#xff0c;先认识下这个庞然大物。( >>> 表示调用到&#xff…

Git可视化极简易教程 — Git GUI使用方法

Git可视化极简易教程 — Git GUI使用方法 学习了&#xff1a;http://www.runoob.com/w3cnote/git-gui-window.html转载于:https://www.cnblogs.com/stono/p/9026292.html

如何用堆栈来保存和恢复滚动条位置

问题背景 在单页应用中&#xff0c;翻页一般通过display:none将先前的面板&#xff08;一般就是个div容器&#xff09;隐藏&#xff0c;然后将本次需要展现的面板设置成display:block&#xff08;当然&#xff0c;还可能加点css切换动画&#xff0c;不过不影响我们本次的讨论结…

如何在Hibernate中维护表的历史记录

为了维护数据库的历史记录或跟踪数据库表行的修改&#xff0c;我们创建了一个版本表&#xff0c;其中包含与原始表相同的字段。每当原始表被更改时&#xff0c;我们都会在版本表中创建另一个条目。 因此&#xff0c;对于每个更新查询&#xff0c;我们都必须在版本表中编写一个插…

java批量提取文件夹名称_bat 批量提取指定目录下的文件名

bat 批量提取指定目录下的文件名下面是批量获取指定目录下的文件名的核心代码echo offecho text inputset inputset /p input:echo %input% is inputcd %input%rem echo onfor %%a in (*) do (echo %%a is input)cd ..如下是sql server执行对应脚本文件sqlcmd -Spcserver -dmas…

埃及分数The Rotation Game骑士精神——IDA*

IDA*&#xff1a;非常好用的搜索&#xff0c;可以解决很多深度浅&#xff0c;但是规模大的搜索问题。 估价函数设计思路&#xff1a;观察一步最多能向答案靠近多少。 埃及分数 题目大意&#xff1a; 给出一个分数&#xff0c;由分子a 和分母b 构成&#xff0c;现在要你分解成一…

[UE4]创建Shooter基类,2种方法

一、可以通过直接修改"BP_FPPCharacter"的名字为“BP_Shooter”作为基类&#xff0c;然后新建一个"BP_FPPCharacter"继承自“BP_Shooter”。 这种方法适用于各个类对"BP_FPPCharacter"依赖不多的情况。 二、创建一个“BP_Shooter”继承于“Chara…

美团扫码付的前端可用性保障实践

开篇 2017年&#xff0c;美团金融前端遇到了很多通用性问题&#xff0c;特别是在保障前端可用性的过程中&#xff0c;我们团队也踩了不少“坑”&#xff0c;在梳理完这些问题以后&#xff0c;我们还专门做了第31期线下沙龙给大家进行了分享。不管是在面试过程中与候选人讨论&a…

Servlet上传文件和下载文件示例

Java Web应用程序中的文件上载和下载以及常见任务。 由于最近我写了很多有关Java servlet的文章 &#xff0c;因此我想提供一个使用servlet上传和下载文件的示例示例。 用例 我们的用例是提供一个简单HTML页面&#xff0c;客户端可以在其中选择要上传到服务器的本地文件。 在提…

用java单源最短路径问题_单源最短路径-贪心算法

单源最短路径&#xff0c;关于这个问题的贪心算有点不好理解&#xff0c;分析后续补充&#xff0c;代码也需要后续优化&#xff0c;便于理解package test;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/*** Created by sa…

APPLE STORE

直接在设置中&#xff0c;使用查看APPLE ID是无法更改的&#xff0c;现在必须要有所在区域的信用卡信息&#xff0c;支付方式无法像以前一样选择“无”。 查询后发现&#xff0c;有人说icloud3.0,即这个旧版的可以进行更改&#xff0c;于是下载。 但发现一个问题&#xff0c;输…

vue项目打包后文本溢出代码消失问题

补充 https://www.cnblogs.com/richard1015/p/8526988.html vue webpack 打包编译-webkit-box-orient: vertical 后消失 解决方案 optimize-css-assets-webpack-plugin这个插件的问题 注释掉webpack.prod.conf.js中下面的代码 new OptimizeCSSPlugin({cssProcessorOptions: c…

前端图片canvas,file,blob,DataURL等格式转换

最近用到一些图片相关的操作&#xff0c;记录一下笔记。 将file转化成base64 场景&#xff1a; 获取到一个file类型的图片&#xff0c;如果直接在html中预览&#xff1f;这里就是利用html5的新特性&#xff0c;将图片转换为Base64的形式显示出来。有两种方法&#xff1a; 方法…

java创建异步多线程_Java创建多线程异步执行实现代码解析

实现Runable接口通过实现Runable接口中的run()方法public class ThreadTest implements Runnable {public static void main(String[] args) {Thread thread new Thread(new ThreadTest());thread.start();}Overridepublic void run() {System.out.println("Runable 方式…

Java中的状态设计模式–示例教程

状态模式是行为设计模式之一 。 当对象根据其内部状态更改其行为时&#xff0c;将使用状态设计模式。 如果必须根据对象的状态更改其行为&#xff0c;则可以在对象中使用状态变量&#xff0c;并使用if-else条件块根据状态执行不同的操作。 状态模式用于通过上下文和状态实现提…

JS 循环遍历 总结

一、循环遍历语句 for...in... &#xff08;ES5&#xff09; 语法&#xff1a;javascript for(keys in obj){}适用&#xff1a;遍历对象说明&#xff1a;   1.keys表示obj对象的每一个键值对的键(键名)&#xff0c;所有循环中&#xff0c;需要使用obj[keys]来取到每一个值。 …