`
OneAPM_Official
  • 浏览: 24916 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

用 JMH 检测 Lambdas 序列化性能

阅读更多
本文将介绍如何进行 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 map = acquireMap(“map-name”, 
                                      String.class, Long.class);
map.put(“key”, 1);
long ret = map.applyToKey(“key”, v -> v + 1); // ret == 2


   
这里没有必要知道数据的具体存储位置,如果是远程服务器,就会在那台服务器上对 Lambda 序列化,然后执行,并将结果返回。



上图显示了 OneAPM(http://www.oneapm.com/ai/java.html?utm_source=Community&utm_medium=Article&utm_term=%E7%94%A8%20JMH%20%E6%A3%80%E6%B5%8B%20Lambdas%20%E5%BA%8F%E5%88%97%E5%8C%96%E6%80%A7%E8%83%BD&utm_campaign=AiJavaArti&from=jscljdqcgs) 如何监控和让 Java 应用之间的调用关系可视化。

Capturing Lambda

不获取字段的 Lambda 可以被 Java 更高效地处理,因为每个实例都一样,所以并不需要每次都创建新的对象。但是,若编译时 Lambda 获取到未知值,就需要创建新的对象,并将获取的值保存。


Non capturing Lambda




Function appendStar = s -> s + "*"




Capturing Lambda



String star = "*";
    Function appendStar = s -> s + star;


   
可序列化的 Lambdas


Lambdas 默认是不可序列化的,必须实现一种可序列化的接口。可以使用强制转换把接口类型转换为所需类型的一种方式。


Function appendStar = 
     (Function & Serializable) (s -> s + star);


    
笔者个人不喜欢这样做,因为这样会破坏减少代码的目标。一个解决的方法就是定义自己所需的可序列化的接口。


@FunctionalInterface
public interface SerializableFunction 
       extends Function, Serializable {


      
这就需要如下所写:


SerializableFunction appendStar = s -> s + star;


或者按照这种方法写入:


 R applyToKey(K key, @NotNull SerializableFunction 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 {
    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
分享到:
评论

相关推荐

    序列化性能测试JAVA

    序列化性能测试是评估不同序列化库或技术在处理大量数据时效率的关键环节。本篇文章将深入探讨Java序列化的概念、常见的序列化库以及如何进行性能测试。 首先,我们要理解什么是序列化。Java中的序列化是通过实现`...

    jmh-samples-1.17.1-sources.zip

    这个"jmh-samples-1.17.1-sources.zip"压缩包包含了JMH的1.17.1版本的源代码样本,为开发者提供了如何有效使用JMH进行性能测试的示例。 JMH的核心目标是提供一种精确、可重复且可靠的基准测试方法,帮助开发者评估...

    jmh-core-1.3.3.zip

    Avro是Apache的一个数据序列化系统,广泛应用于分布式数据处理。"parquet-avro-extra"可能包含了一些额外的Scala宏,这些宏用于自动生成Parquet模式的投影和筛选谓词。这使得在处理Parquet文件时,能够更高效地进行...

    微基准测试工具:jmh

    在使用JMH时,开发者通常会定义一个或多个基准测试类,每个类包含一个或多个测试方法。这些方法通过特定的JMH注解(如@Benchmark)标记,表示它们是需要被测试的代码片段。JMH提供了一系列注解,例如@Setup、@...

    Java微基准测试实践:使用JMH进行性能分析

    微基准测试是Java性能优化的重要工具,JMH提供了一个简单而强大的框架来实现这一目标。通过合理配置测试、分析结果并避免常见的优化陷阱,开发者可以准确地测量和优化代码性能。

    JMH - Java 微基准测试工具(自助性能测试)完整可运行代码

    JMH的目标是帮助开发者正确地进行性能测试,避免常见的陷阱,并提供一个标准化的测试环境,以便在不同实现之间进行比较。下面我们将深入探讨JMH的相关知识点。 1. **JMH介绍** JMH是由Java开发的,主要用于测量和...

    jmh-perf-tests:各种JMH性能测试

    "jmh-perf-tests"项目就是利用JMH对Hibernate的某些关键操作进行性能评估,如对象持久化、查询执行、事务管理等。通过JMH,开发者可以发现潜在的性能瓶颈,并针对性地优化代码。 四、JMH测试实例 在"jmh-perf-...

    使用JMH进行微基准测试不要猜,要测试!Java开发Jav

    使用JMH提供的命令行工具,你可以运行基准测试套件,并获得详尽的性能报告。这些报告包括平均时间、标准偏差、吞吐量等指标,帮助你理解代码的性能表现。 5. **避免常见错误** - **避免过早优化**:在有数据支持...

    jmh.rar_jmh The

    综合来看,"jmh.rar_jmh The" 提供了一个学校教务管理的信息化解决方案,涵盖了成绩管理的核心需求,并且具有自动化和智能化的特点。其包含的文档可能为理解、使用或改进该系统提供了重要的信息。对于学校管理者和...

    Android代码-jmh-gradle-plugin

    = JMH Gradle Plugin :jmh-version: 1.21 :plugin-version: 0.4.8 image:http://img.shields.io/travis/melix/jmh-gradle-plugin/master.svg["Build Status (travis)", link=...

    lambda-benchmark:Java 8 Lambda和Java 7匿名类之间的比较JMH基准

    而在Java 8中,同样的功能可以使用Lambda表达式简化为: ```java Runnable r = () -> { // 代码体 }; ``` "lambda-benchmark"项目通过JMH进行性能测试,JMH是Oracle开发的一个用于编写微基准测试的框架,它可以...

    JMH 气象传真图播发表

    **JMH气象传真图播发表详解** 日本气象厅(Japan Meteorological Agency,简称JMH)是全球重要的气象服务机构之一,其发布的气象传真图对于航海、航空、气象预报以及相关行业至关重要。JMH的气象传真图播发表列出了...

    idea-jmh-plugin.jar

    IDEA JMH基准测试插件 微基准测试,他是测的某一个方法的性能到底是好或者不好,换了方法的实现之后他的性能到底好还是不好。

    jmh-generator-bytecode-0.7.2.zip

    【标题】"jmh-generator-bytecode-0.7.2.zip" 提供的是Java Microbenchmark Harness(JMH)的一个工具,用于生成字节码级别的性能基准测试。JMH是Java平台上的一个开源框架,它专注于提供准确且可重复的性能测量。这...

    JMH简介Java开发Java经验技巧共8页.pdf.zi

    这个文档可能包含了8页关于如何使用JMH进行性能调优,以及在Java开发中的实用经验和技巧。 【描述】:“JMH简介Java开发Java经验技巧共8页.pdf.zip” 描述了文档的格式,即它是一个被ZIP压缩的PDF文件,内容是关于...

    jmh-visualizer:直观地探索您的JMH基准

    JMH可视化器 直观地查看您的基准! 在线版本位于 ! 带有2个配套项目: 特征 无服务器架构-所有操作均在您的浏览器中本地进行 可视化按基准测试类别分组的(一个JSON文件)的基准测试 带有分数和分数错误的垂直条形...

Global site tag (gtag.js) - Google Analytics