首先,让我们谈谈测试方法:

所有 测试 都 在 我的 笔记本 上 运行i7  2.0 Ghz  16 Gb  Ubuntu  18.4  和 OpenJdk  11
 
graal  VM  选项:
- Xms6g  - Xmx6g  - XX:+ UseParallelOldGC  - XX:+ UnlockExperimentalVMOptions  - XX:+ UseJVMCICompiler
 
c2  VM  选项:
- Xms6g  - Xmx6g  - XX:+ UseParallelOldGC
 
我 运行 一个 测试 称为 PerformanceTest  在 每个 项目中 ,其 执行 一 结束 ,以 结束 标杆 不断。在 这种 方式 的 编译器 不能 优化 的 代码 为 一个 特定的 情况下。于是 我 选择 了 更快的 结果,假设 它 是 在 一个 没有 GC  和 OS  暂停。所有的 测试 均 运行 单- 线程。

以下是结果:

正如你所看到的,Graal使用Kotlin进行编译在小板上的速度明显更快,并且随着大板随机播放的速度稍快一点。

我怀疑这是因为随着更大的主板内存管理,它占用了大量的运行时间。在任何情况下,增量都是受欢迎的,特别是考虑到我通常在较小的板上玩。

为了测试我的理论,我创建了一个新项目,其中包含一些经典算法的实现,以查看性能的差异。你可以在这里找到它。

目前,有两种算法:Mandelbrot Set生成器和Knapsack解算器。

Mandelbrot集

该Mandelbrot集可能是你见过的最有名的分形-即使你不知道这个名字。

在数学上,它被定义为复平面中所有点的集合,其中函数z < - z ^ 2 + c在迭代时不会发散。生成Set迭代复杂平面上某些点的函数并从中创建图像非常容易。

由于这里的目标是性能而不是图形,我使用文本图形保持简单。

让我们从查看Mandelbrot Set的代码开始。

数据 类 Complex(val  r:Double,val  i:Double){
    操作员 欢乐 时光(其他:复杂)=
        复杂(
            r  =  这个。r  *  其他。r  -  这个。我 *  其他。我,
            我 =  这个。我 *  其他。r  +  这个。r  *  其他。一世
    操作员 乐趣 加(其他:复杂)=
        复杂的(- [R  =  此。[R  +  等。[R ,我 =  此。我 +  其他。我)
    操作员 乐趣 减去(其他:复杂)=
        复杂的(- [R  =  此。[R  -  其他。ř,我 =  此。我 -  其他。我)
    fun  squared()=  this  *  this
    有趣的是 squaredModule()=  r  *  r  +  i  *  i
    有趣的 双。toComplex()=  Complex(r = this,i = 0.0)
}
有趣的 mandelSet(initZ:Complex,c:Complex,maxIter:Int):Int {
    var  z  =  initZ
    (1.。MAXITER)。forEach {
        z  =  z。平方()+  c
        如果(ž。squaredModule()> =  4)
            归还 它
    }
    return  maxIter
}

您可以在此处看到如何使用运算符重载和数据类来表示复数,这样可以真正简化代码并使其更易于理解。

一旦我们在Complex类中定义了对复数进行操作的规则,该  mandelSet 函数只需要检查操作z < - z ^ 2 + c是否“转义”,并且万一,经过多次迭代后,它将超过4的门槛。

在这里,您可以在AsciiArt中呈现的输出中看到Mandelbrot Set的特征心形图:

背包问题

该背包问题可以通过多种方式来定义。想象一下,作为一个刚刚闯入手表店的小偷。如果您没有超过背包中可携带的最大重量,您可以偷走任意数量的手表。

作为一个实用的小偷,你绝对想要优化你带来的手表的价值。每只手表都有价格和重量。因此,您需要找到具有给定重量的最大总价的手表组。

实际应用包括优化CNC应用的削减和材料以及分配广告预算的营销策略。

例如,让我们看一下只有三只手表的商店,定义如下:

val  shop  =  背包。商店(
    观察(重量 =  1,价格 =  1),
    观察(重量 =  3,价格 =  2),
    观看(重量 =  1,价格 =  3)

如果我们的最大重量为1,那么我们最好选择第三只手表,而不是第一只手表,因为价值更高。

如果我们的最大权重为3,我们可以选择数字2(价格2)或数字1和3(价格1 + 3)。在这种情况下,最好选择1和3,即使它们的总重量小于最大值。

这些是这个商店的完整解决方案:

assertEquals(3,selectWatches(shop,maxWeight  =  1))
assertEquals(4,selectWatches(shop,maxWeight  =  2))
assertEquals(4,selectWatches(shop,maxWeight  =  3))
assertEquals(5,selectWatches(shop,maxWeight  =  4))
assertEquals(6,selectWatches(shop,maxWeight  =  5))

如您所见,随着可用手表数量的增加,可能的选择数量变得非常非常快。这是一个经典的NP-Hard问题。

要在合理的时间内解决它,我们需要作弊并使用动态编程。我们可以使用针对每组手表的已经优化的解决方案构建地图,因此,我们可以避免每次重新计算它们。

通用算法基于基于递归的穷举搜索。这是解决它的Kotlin代码,在memoization函数和最大值的递归搜索中分开。

typealias  Memoizer  =  MutableMap < String,Int >
 
有趣的 priceAddingElement(备忘录:Memoizer,shop:Set < Watch >,选择:Set < Watch >,maxWeight:Int,priceSum:Int):Int  =
    商店。过滤 { !(它 在 选择中)&&  它。重量 <=  maxWeight }
        。地图 {
            selectWatches(
                备忘录,
                商店,
                maxWeight  -  它。重量,
                选择 +  它,
                priceSum  +  它。价格)}
        。过滤 { it  >  priceSum }
        。max()?:priceSum
 
 
有趣的 selectWatches(备忘录:Memoizer,shop:Set < Watch >,maxWeight:Int,choice:Set < Watch >,priceSum:Int):Int  =
    memoization(memo,generateKey(choice)){
        priceAddingElement(备忘录,商店,选择,maxWeight,priceSum)}
 
 
private  fun  memoization(memo:Memoizer,key:String,f :()- >  Int):Int  =  when(val  w  =  memo [ key ]){
        null  - >  f()。还 { memo [ key ] =  it }
        否则 - >  w
    }

我真的很喜欢Kotlin如何让你清楚地表达意图,而不必重复自己。如果您不了解Kotlin,我希望这段代码可以吸引您,并在某一天尝试它。

基准

现在,您正在等待的部分,让我们比较Graal与优秀的'C2编译器'的性能。

让我们记住,Graal是用Java编写的,并且正在利用编译器领域的新研究,但它仍然相对年轻。另一方面,C2非常好地调整和成熟。

第一个惊喜是Mandelbrot的例子:

说实话,我没想到性能会有这么大的差异。Graal比C2快约18%!只是为了确定,我用稍微不同的公式再次尝试并收到了相同的结果。Graal在编写Kotlin的计算时非常精彩。

而现在,更令人惊讶的是,背包测试:

在这里,Graal慢了54%!

做一些分析,我发现我的代码大部分时间都花在了为memoization生成密钥的函数上。

为了确保我是正确的,我订购了套装,然后将其转换为字符串。这是很多不必要的工作,它依赖于  HashSet Java实现。

所以,我改变了方法来生成密钥:

private  fun  generateKey(choice:Set < Watch >):String  = 
  选择。sortedBy { “$ {it.price}  -  $ {it.weight}” }。toString()

对此:

private  fun  generateKey(choice:Set < Watch >):String  =
   选择。地图 { 它。hashCode()}。sorted()。joinToString(“”)

新功能更快,因为它对手表的哈希值进行排序,这些哈希值是唯一的,然后将它们连接成一个字符串。

请注意,我们不能简单地使用Set的哈希值,因为可能存在哈希冲突。我实际上尝试过并验证它开始发出错误的结果。

可以为Set创建更安全的散列方法,但这里的目标不是最大限度地优化算法,而是编写高效且清晰的Kotlin代码。

现在,让我们来看看惯用的Kotlin的结果:

在这里,Graal再次明显比C2快,总的来说,新的密钥生成器比以前的实现快得多。

我对这些结果的猜测是,C2经过大量优化(使用内在函数等)用于典型的Java用法,而Graal擅长编译小方法和轻量级对象,这是典型的惯用Kotlin。

我希望这篇文章能激励更多Kotlin开发人员使用Graal!快乐的编码!

JVM Advent Calendar:将Kotlin性能与Graal和C2进行比较相关推荐

  1. 比较Kotlin性能与Graal和C2

    您可能听说过Graal,这是用Java编写的JVM的新JIT编译器. 自Java10开始,它就可以在JDK中使用,将来可能会成为JDK的标准. 如果您有兴趣,可以在这里找到更多信息: https : ...

  2. kotlin与go性能_比较Kotlin性能与Graal和C2

    kotlin与go性能 您可能听说过Graal,这是用Java编写的JVM的新JIT编译器. 自Java10起,它就可以在JDK中使用,将来可能会成为JDK的标准. 如果您有兴趣,可以在这里找到更多信 ...

  3. Excel Advent Calendar for 2010

    Last December, I posted an Excel Advent Calendar, and it was surprisingly popular, throughout the ye ...

  4. JVM调优全面探讨-性能设计沉思录(1)

    为什么要jvm gc可能是java程序猿或非java程序猿讨论最多的话题,到底怎么回事? 本篇内容:内存管理发展史,JVM内存管理分析和实践(基础知识),JVM8调优(内存运行原理和编译优化)  :2 ...

  5. jvm调优工具_JVM性能调优监控工具jps、jstack、jmap、jhat、hprof使用详解

    来自:ITeye博客, 作者:Josh_Persistence 链接:https://www.iteye.com/blog/josh-persistence-2161848 现实企业级Java应用开发 ...

  6. Kotlin 性能优化利器 —— Sqeuence 原理浅析

    前言 本文将介绍 Kotlin 中 序列(Sequence)的概念及使用,并介绍该惰性集合操作对集合链式调用性能优化背后的原理. 目录 序列(Sequence) 概念 在使用 Kotlin 集合操作符 ...

  7. 深入理解JVM虚拟机(三):虚拟机性能监控工具

    本博客将讲解Java虚拟机性能监控工具的使用以及对Java虚拟机进行性能监控的实验.Java开发人员需要对虚拟机性能监控工具的使用进行掌握,这是很有必要的. 1.概述 给一个系统定位问题的时候,知识. ...

  8. Java虚拟机:常见JVM参数配置和GC性能优化

    一.常见的JVM参数配置: 1.垃圾回收统计信息: -XX:+PrintGC     打印GC简要信息 -XX:+PrintGCDetails打印GC的详细信息 -XX:+PrintGCTimeSta ...

  9. jvm 参数_6个提高性能的JVM参数

    截止到2020年五月,JVM中仅仅只是关于垃圾回收和内存相关的参数就已经超过600个.如果算上其他方面的参数,JVM相关的总参数能轻松超过1000个.参数太多了,弄得人很懵逼.在这边文章中,我们只选取 ...

最新文章

  1. 【 FPGA 】状态机,FPGA的灵魂
  2. 支付接入开发的陷阱有多深?
  3. 新BOJ 87. 日期
  4. GDCM:区分音量DiscriminateVolume的测试
  5. 运算符重载 返回类型说明符后加_Java学习:运算符的使用与注意事项
  6. dmp文件查看表空间_innoDb文件
  7. web 前端routine
  8. QList、QVector、QMap容器类
  9. java实现英文文件单词搜索系统_java对于目录下文件的单词查找操作代码实现
  10. 未来语音识别技术的发展趋势会如何
  11. C语言函数库帮助文档
  12. SVN同步分支代码到主干
  13. GMP文件分类与编码管理规程
  14. Android Studio设置签名密钥
  15. 【将金令】炒白银,切忌!切忌!
  16. C# 实现定时/循环任务
  17. java freemarker转PDF和Word
  18. MATLAB 彩色图转灰色图处理
  19. python 之 for 循环
  20. Someone‘s Acting Sus....

热门文章

  1. 构建煤矿物联网大数据平台思路(2)-实时数据库与时序数据库
  2. Java基础篇——字符串处理(String,StringBuffer,StringBuild)
  3. 23种设计模式(合集)
  4. wps文档怎么删除空白段,删除空白段的操作方法
  5. 我的老婆很聪明(一)
  6. 关于2022年6月青少年等级考试的几点说明:
  7. CoVOS:无需解码!利用压缩视频比特流的运动矢量和残差进行半监督的VOS加速(CVPR 2022)...
  8. mysql四舍五入函数取两位小数_MySQL四舍五入函数ROUND(x)、ROUND(x,y)和TRUNCATE(x,y)
  9. Python 数组截取
  10. Outlook签名设置不完全指北