本文将介绍如何进行 Java Lambdas 序列化性能检测、Lambdas 的重要性以及 Lambdas 在分布式系统中的应用。

Lambdas 表达式是 Java 8 中万众期待的新特性,其若干用途包括:

  1. 为匿名内部类减少所需样本代码。

  2. 缩小值的作用域。Lambdas 表达式中的 this 不会涉及到外部类,减少了内存泄露。

  3. 轻松集成现有 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 序列化性能的更多相关文章

  1. 各种Java序列化性能比较

    转载:http://www.jdon.com/concurrent/serialization.html 这里比较Java对象序列化 XML JSON  Kryo  POF等序列化性能比较. 很多人以 ...

  2. ServiceStack.Text / Newtonsoft.Json 两种json序列化性能比较

    JSON序列化现在应用非常多,尤其在前后端分离的情况下,平常大多数C#下都使用Newtonsoft.Json来操作,量少的情况下,还可以忽略,但量大的情况下就要考虑使用ServiceStack.Tex ...

  3. 目标检测模型的性能评估--MAP(Mean Average Precision)

    目标检测模型中性能评估的几个重要参数有精确度,精确度和召回率.本文中我们将讨论一个常用的度量指标:均值平均精度,即MAP. 在二元分类中,精确度和召回率是一个简单直观的统计量,但是在目标检测中有所不同 ...

  4. java原生序列化和Kryo序列化性能比较

    简介 最近几年,各种新的高效序列化方式层出不穷,不断刷新序列化性能的上限,最典型的包括: 专门针对Java语言的:Kryo,FST等等 跨语言的:Protostuff,ProtoBuf,Thrift, ...

  5. PHP5.5四种序列化性能对照

    json_encode,serialize,igbinary,msgpack四种序列化方式,在之前已经有过相关的測试,PHP5.5这方面的測试临时没有,这次測试基于PHP5.5,而且測试用例,http ...

  6. Delphi 10.2 JSON与对象/结构体序列化性能提高100多倍

    今天在盒子闲逛,无意中看到有人说XE7自带的Json对象序列化很慢,帖子在这里:http://bbs.2ccc.com/topic.asp?topicid=464378;经过测试的确如此.     但 ...

  7. 检测SqlServer服务器性能

    通过性能监视器监视 Avg. Disk Queue Length   小于2 Avg. Disk sec/Read , Avg. Disk sec/Write  小于10ms 可以用数据收集器定时收集 ...

  8. 基音检测算法的性能: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í) ...

  9. iOS性能检测之Instrunments - 几种常用工具简单介绍

    Instrunments:  没错,就是这货,很多人平时开发可能不一定会用到这个,但我要说的是,学会使用它,会让你加分不少哦 先来一张全家福: 1.打开方式 或者 两种方式都行. 2.今天主要介绍一下 ...

随机推荐

  1. webstorm卡、闪退以及win10中jdk配置

    今天 webstorm 突然一直处于 indexing 索引状态,然后就卡死,重装也无法解决. 搜了一下后,有人说使用 64 位客户端打开就ok. 尝试打开 64 位的客户端,但是报错,没有64位 j ...

  2. 关于c#生成word。

    需求:需要把数据做成这样的效果.一个页面展示一个r单子数据. object filename = ""; Object Nothing = System.Reflection.Mi ...

  3. sqlserver 理解数据集

    数据集分四类: 1.A∩B,既是所求数据集既在A中,又在B中 2.A∪B,既所求数据在数据集A中,或在数据集B中 3.A-B,既所求数据在数据集A中,不在数据集B中 4.B-A,既所求数据在数据集B中 ...

  4. AlwaysOn实现只读路由

    1.配置只读路由 ①配置A副本的只读路由属性(ReadOnly代表‘只读意向’) ALTER AVAILABILITY GROUP [testAG] MODIFY REPLICA ON N'WIN-1 ...

  5. WebClient.UploadValues Post中文乱码的解决方法

    //using (System.Net.WebClient wc = new System.Net.WebClient()) //{ // wc.Encoding = Encoding.GetEnco ...

  6. asp.net 备份和恢复数据库

    观看了Insus的视频写下来的,代码可能有点冗长,如有好的想法的,可以多交流. 前台: <form id="form1" runat="server"&g ...

  7. JavaScript中的apply与call与arguments对象

    (一) call方法 语法:presentObj.call(thisObj,arg1,arg2,arg3...) 参数thisObj :将被用作当前对象presentObj的对象. 当thisObj无 ...

  8. 简单jquery 鼠标悬停提示效果

    记得自己引入jq插件哦~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  9. The method getContextPath() is undefined for the type ServletContext

    我出错时,到网上说得是版本问题,我找到对应的包javax-servlet5.1.12.jar,把它删了,居然不报错了,原来是和包servlet-2_5-api.jar冲突了

  10. WIX Custom Action (immediate, deffered, rollback)

    Following content is directly reprinted from From MSI to WiX, Part 19 - The Art of Custom Action, Pa ...