用 JMH 检测 Lambdas 序列化性能
本文将介绍如何进行 Java Lambdas 序列化性能检测、Lambdas 的重要性以及 Lambdas 在分布式系统中的应用。
Lambdas 表达式是 Java 8 中万众期待的新特性,其若干用途包括:
为匿名内部类减少所需样本代码。
缩小值的作用域。Lambdas 表达式中的 this 不会涉及到外部类,减少了内存泄露。
轻松集成现有 API 与新的 Streams API。
Lambdas 另一个鲜有人知的特点就是可被序列化。
为什么对 Lambda 序列化?
序列化有益于对象的状态持久化和网络传输。 Lambdas 应该尽可能无状态,这样就可以保存 Lambdas ,但这并不是典型的用例。
Lambdas 表达式的目的是给程序库传递代码片段,使之与库中正在运行的程序交互。但是如果程序库支持像 Chronicle Engine 这样的分布式系统,那又会怎么样?
什么是 Chronicle Engine?
Chronicle Engine 是一个库,可让用户使用各自的应用程序远程访问数据结构,无论是用 Java、C# 客户端,还是用 NFS 文件系统。该库还支持存储和持久化数据,也支持复制。
分布式系统中的 Lambdas
对于某些局部运行的操作,使用 Lambdas 执行不失为一种简单可行的方法。示例操作如下:
MapView<String, Long> map = acquireMap(“map-name”,
String.class, Long.class);
map.put(“key”, 1);
long ret = map.applyToKey(“key”, v -> v + 1); // ret == 2
这里没有必要知道数据的具体存储位置,如果是远程服务器,就会在那台服务器上对 Lambda 序列化,然后执行,并将结果返回。

上图显示了 OneAPM 如何监控和让 Java 应用之间的调用关系可视化。
Capturing Lambda
不获取字段的 Lambda 可以被 Java 更高效地处理,因为每个实例都一样,所以并不需要每次都创建新的对象。但是,若编译时 Lambda 获取到未知值,就需要创建新的对象,并将获取的值保存。
Non capturing Lambda
Function<String, String> appendStar = s -> s + "*"
Capturing Lambda
String star = "*";
Function<String, String> appendStar = s -> s + star;
可序列化的 Lambdas
Lambdas 默认是不可序列化的,必须实现一种可序列化的接口。可以使用强制转换把接口类型转换为所需类型的一种方式。
Function<String, String> appendStar =
(Function<String, String> & Serializable) (s -> s + star);
笔者个人不喜欢这样做,因为这样会破坏减少代码的目标。一个解决的方法就是定义自己所需的可序列化的接口。
@FunctionalInterface
public interface SerializableFunction<I, O>
extends Function<I, O>, Serializable {
这就需要如下所写:
SerializableFunction<String, String> appendStar = s -> s + star;
或者按照这种方法写入:
<R> R applyToKey(K key, @NotNull SerializableFunction<E, R> function) {
该库的调用者就可以如下所写,而不需要任何样本代码。
String s = map.applyToKey(“key”, s-> s + “*”);
Lambdas 的实时查询
利用序列化的 Lambdas,可进行如下所示的实时查询:
// print the last name of all the people in NYC
acquireMap(“people”, String.class, Person.class).query()
.filter(p -> p.getCity().equals(“NYC”)) // executed on the server
.map(p → p.getLastName()) // executed on the server
.subscribe(System.out::println); // executed on the client.
可查询接口是必需的,因此过滤器 Predicate 和 map 函数也必须隐式可序列化。如果需要使用 Streams API,那就要使用早期较为复杂的数据类型转换函数 cast。
序列化 Lambdas 的性能
笔者曾经在一个字符串中写入符号“*”,并使用 JMH 对简单的序列化的和反序列化的 Lambda 进行时延采样,然后比较采集和非采集两种情况下的时延,发送枚举时两种情况下的时延也一并比较。代码和结果如下表所示:
99.99%的时延意味着该试验的99.99%都是在时延之中。时间都用微秒计算。
| Test | Typical latency | 99.99% latency |
|---|---|---|
| Java Serialization, non-capturing | 33.9 µs | 215 µs |
| Java Serialization, capturing | 36.3 µs | 704 µs |
| Java Serialization, with an enum | 7.9 µs | 134 µs |
| Chronicle Wire (Text), non-capturing | 20.4 µs | 147 µs |
| Chronicle Wire (Text), capturing | 22.5 µs | 148 µs |
| Chronicle Wire (Text), with an enum | 1.2 µs | 5.9 µs |
| Chronicle Wire (Binary), non-capturing | 11.7 µs | 103 µs |
| Chronicle Wire (Binary), capturing | 12.7 µs | 135 µs |
| Chronicle Wire (Binary), with an enum | 1.0 µs | 1.2 µs |
为什么要使用枚举?
使用 Lambda 是很简单,但它效率不高时,就需要找一个备选方案。所以当 Lambda 的使用造成性能问题时,就要使用备选方案。
enum Functions implements SerializableFunction<String, String> {
APPEND_STAR {
@Override
public String apply(String s) {
return s + '*';
}
}
}
为考察使用枚举所起到的作用,可以比较发送到服务器的数据量的多少,在那里可以看到所有序列化的数据。
下面就是当在 TextWire 中序列化时,非采集的 Lambda 的情况。(基于 YAML)
!SerializedLambda {
cc: !type lambda.LambdaSerialization,
fic: net/openhft/chronicle/core/util/SerializableFunction,
fimn: apply,
fims: (Ljava/lang/Object;)Ljava/lang/Object;,
imk: 6,
ic: lambda/LambdaSerialization,
imn: lambda$textWireSerialization$ea1ad110$1,
ims: (Ljava/lang/String;)Ljava/lang/String;,
imt: (Ljava/lang/String;)Ljava/lang/String;,
ca: [
]
}
枚举序列化如下所示:
!Functions APPEND_STAR
注意:当需要采集某些值时,不可以使用枚举。我们要做的就是让你通过传递有附加参数的枚举,以获得最有效的组合。
使用枚举就像存储过程
用枚举代替 Lambdas 的一个好处就是,可以跟踪所有功能客户执行和整合的方式。某些函数使用广泛,运用枚举使得修复任一单独函数中产生的bug更为容易,因此会被经常使用。举一个简单的例子,MapFunction 起初有很多不同的 Lambdas,而现在已经被归为一类。
结论
如果所使用的 API 支持,可将 Lambdas 用于分布式应用程序。如果需要附加的性能,也可以使用枚举。
原文地址:https://dzone.com/articles/measuring-the-serialization-performance-of-lambdas
用 JMH 检测 Lambdas 序列化性能的更多相关文章
- 各种Java序列化性能比较
转载:http://www.jdon.com/concurrent/serialization.html 这里比较Java对象序列化 XML JSON Kryo POF等序列化性能比较. 很多人以 ...
- ServiceStack.Text / Newtonsoft.Json 两种json序列化性能比较
JSON序列化现在应用非常多,尤其在前后端分离的情况下,平常大多数C#下都使用Newtonsoft.Json来操作,量少的情况下,还可以忽略,但量大的情况下就要考虑使用ServiceStack.Tex ...
- 目标检测模型的性能评估--MAP(Mean Average Precision)
目标检测模型中性能评估的几个重要参数有精确度,精确度和召回率.本文中我们将讨论一个常用的度量指标:均值平均精度,即MAP. 在二元分类中,精确度和召回率是一个简单直观的统计量,但是在目标检测中有所不同 ...
- java原生序列化和Kryo序列化性能比较
简介 最近几年,各种新的高效序列化方式层出不穷,不断刷新序列化性能的上限,最典型的包括: 专门针对Java语言的:Kryo,FST等等 跨语言的:Protostuff,ProtoBuf,Thrift, ...
- PHP5.5四种序列化性能对照
json_encode,serialize,igbinary,msgpack四种序列化方式,在之前已经有过相关的測试,PHP5.5这方面的測试临时没有,这次測试基于PHP5.5,而且測试用例,http ...
- Delphi 10.2 JSON与对象/结构体序列化性能提高100多倍
今天在盒子闲逛,无意中看到有人说XE7自带的Json对象序列化很慢,帖子在这里:http://bbs.2ccc.com/topic.asp?topicid=464378;经过测试的确如此. 但 ...
- 检测SqlServer服务器性能
通过性能监视器监视 Avg. Disk Queue Length 小于2 Avg. Disk sec/Read , Avg. Disk sec/Write 小于10ms 可以用数据收集器定时收集 ...
- 基音检测算法的性能:Performance Evaluation of Pitch Detection Algorithms
http://access.feld.cvut.cz/view.php?cisloclanku=2009060001 Vydáno dne 02. 06. 2009 (15123 přečtení) ...
- iOS性能检测之Instrunments - 几种常用工具简单介绍
Instrunments: 没错,就是这货,很多人平时开发可能不一定会用到这个,但我要说的是,学会使用它,会让你加分不少哦 先来一张全家福: 1.打开方式 或者 两种方式都行. 2.今天主要介绍一下 ...
随机推荐
- 目前项目wordpress插件记录
Restrict User Content WordPress 后台只显示当前登录用户的文章.页面和媒体 Client Dash 可以根据不同的角色生成不同的后台的菜单
- SharpDevelop 编译时,任务失败,因为未找到“resgen.exe”的解决方法
在git clone sprite的项目,在本地编译的时候,会出现 任务失败,因为未找到“resgen.exe”,或未安装正确的 Microsoft Windows SDK.任务正在注册表项 HKEY ...
- spring beans的写入工具——spring-beans-writer
spring-beans-writer是我曾经为动态生成spring beans配置文件做的一个写入工具,托管地址: https://github.com/bluejoe2008/spring-bea ...
- 【MINA】用mina做业务服之间的通信,实现业务负载均衡思路
学习mina目的还是搭建通信架构,学完mina我们了解了如何实现客户端和服务端,也就是一个正常channel我们是知道怎么建立的 但是问题是,我们应用环境通信分为两种 1.前后端通信 其实这个比较好实 ...
- Azure Redis Cache作为ASP.NET 缓存输出提供程序
前一篇文章<Azure Redis Cache作为ASP.NET Session状态提供程序 >我们已经知道如何将ASP.NET应用程序Session存储在Redis Cache中,这里我 ...
- Android的自动对焦
1,什么是自动对焦? ---安卓的自动对焦的概念是指能够在指定的位置计算出准确的焦点位置. 这个就好像是传统意义上的手动对焦.但是google是这个意思. 2.什么是追焦? ----安卓的追焦是指FO ...
- zabbix的邮件报警
邮件报警插件 #!/usr/bin/python #coding:utf-8 import smtplib from email.MIMEText import MIMEText import os ...
- Vijos P1325桐桐的糖果计划
> P1325桐桐的糖果计划 标签:**图结构 强连通分量** 描述 桐桐很喜欢吃棒棒糖.他家处在一大堆糖果店的附近. 但是,他们家的区域经常出现塞车.塞人等情况,这导致他不得不等到塞的车或人走 ...
- 【搭建开发环境】Linux 中安装 Eclipse 进行 C/C++ 开发
引言 Linux 中选用 C/C++ 的 IDE,推荐 Eclipse. 涉及工具:JDK,Eclipse. 欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovi ...
- 1-了解Python
为什么使用python: 软件质量: 可读写.一致性.软件质量 支持软件开发的高级重用机制 提供开发者的效率: 代码只有java或C++的1/5~1/3 无须编译链接,提高了程序原的效率 程序的可移植 ...