kotlin与go性能

您可能听说过Graal,这是用Java编写的JVM的新JIT编译器。 自Java10起,它就可以在JDK中使用,将来可能会成为JDK的标准。

如果您有兴趣,可以在这里找到更多信息: https : //www.infoq.com/articles/Graal-Java-JIT-Compiler

去年,我主要与Kotlin合作,作为个人项目,我实现了一个机器人来玩Kotlin中的Go游戏。 您可以在这里找到源: https : //github.com/uberto/kakomu

可以想象,在任何游戏机器人(国际象棋,围棋等)中,计算机播放器的能力都与其速度成正比。 在我的情况下,主引擎基于MonteCarloSearch算法,该算法模拟成千上万的随机游戏以评估每个位置。

那么,为什么不让Graal参加呢?

从Java 10开始,您可以在开始时仅使用VMOptions激活Graal。

首先介绍一下测试方法:

All tests run on my Notebook with i7 2.0Ghz 16Gb Ubuntu 18.4 with OpenJdk 11graal VM Options:
-Xms6g -Xmx6g -XX:+UseParallelOldGC -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompilerc2 VM Options:
-Xms6g -Xmx6g -XX:+UseParallelOldGCI run a test called PerformanceTest in each project which execute a end to end benchmark continuously. In this way the compiler cannot optimize the code for a specific case. Then I choose the faster result, assuming it is the one without GC and OS pauses. All tests are running mono-thread.

结果如下:

如您所见,Graal编译的Kotlin在小板游戏中明显更快,而在大板游戏中则仅稍快一些。

我怀疑这是因为使用更大的板卡内存管理会占用很大一部分运行时间。 无论如何,增加都是令人欢迎的,特别是考虑到我通常在较小的棋盘上比赛。

为了检验我的理论,我创建了一个新项目,其中包含一些经典算法的实现,以查看性能上的差异。 您可以在这里找到它: https : //github.com/uberto/kotlin-perf

目前有两种这样的算法:Mandelbrot集生成器和Knapsack求解器。

曼德布罗集

维基百科参考: https : //en.wikipedia.org/wiki/Mandelbrot_set

Mandelbrot集可能是最著名的分形形状,即使您不知道其名称,您也可能已经看过。

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

因为这里的目标是性能而不是图形,所以我使用文本图形使事情变得简单。

让我们开始看一下Mandelbrot集的代码。

data class Complex(val r: Double, val i: Double){operator fun times(other: Complex) =Complex(r = this.r * other.r - this.i * other.i,i = this.i * other.r + this.r * other.i)operator fun plus(other: Complex) =Complex(r = this.r + other.r, i = this.i + other.i)operator fun minus(other: Complex) =Complex(r = this.r - other.r, i = this.i - other.i)fun squared() = this * thisfun squaredModule() = r * r + i * ifun Double.toComplex() = Complex(r=this, i=0.0)
}
fun mandelSet(initZ: Complex, c:Complex, maxIter: Int): Int {var z = initZ(1..maxIter).forEach{z = z.squared() + cif (z.squaredModule() >= 4)return it}return maxIter
}

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

一旦我们在Complex类中定义了对复数进行运算的规则,mandelSet函数仅需检查z <-z ^ 2 + c运算是否在“转义”,并且在经过多次迭代后会超过阈值4。

在这里,您可以在AsciiArt渲染的输出中看到Mandelbrot Set的典型心形形状:

背包问题

有关背包问题的维基百科参考: https : //en.wikipedia.org/wiki/Knapsack_problem

背包问题可以用几种方法来定义。 想象一下是一个刚闯入一家手表店的小偷。 只要您不超过背包的最大重量,就可以偷很多手表。

作为一个理性的小偷,您肯定想优化您将带出的手表的价值。 每只手表都有价格和重量。 因此,您需要找到给定重量的总价格最高的手表组。

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

例如,让我们从一家只定义了3个手表的商店开始:

val shop = Knapsack.shop(Watch(weight = 1, price = 1),Watch(weight = 3, price = 2),Watch(weight = 1, price = 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代码,分为备忘录功能和最大值的递归搜索。

typealias Memoizer = MutableMap<String, Int>fun priceAddingElement(memo: Memoizer, shop: Set<Watch>, choice: Set<Watch>, maxWeight: Int, priceSum: Int): Int =shop.filter { !(it in choice) && it.weight <= maxWeight }.map {selectWatches(memo,shop,maxWeight - it.weight,choice + it,priceSum + it.price) }.filter { it > priceSum }.max() ?: priceSumfun selectWatches(memo: Memoizer, shop: Set<Watch>, maxWeight: Int, choice: Set<Watch>, priceSum: Int): Int =memoization(memo, generateKey(choice)) {priceAddingElement(memo, shop, choice, maxWeight, priceSum)}private fun memoization(memo: Memoizer, key: String, f: () -> Int): Int = when (val w = memo[key]) {null -> f().also { memo[key] = it }else -> w}

我非常喜欢Kotlin如何允许表达自己的意图而不必重复自己。 如果您不了解Kotlin,我希望这段代码能引起您的兴趣,有一天可以尝试一下。

基准测试

现在,您一直在等待的部分。 让我们比较一下Graal和旧的C2编译器的性能。

让我们记住Graal是用Java编写的,它利用了编译器领域的新研究,但是它仍然相对较年轻。 另一边的C2调优和成熟。

第一个惊喜是关于Mandelbrot的示例:

老实说,我没想到会有如此大的性能差异。 Graal比C2快18%! 只是要确保我尝试使用具有相同结果的略有不同的公式。 Graal确实非常适合编译Kotlin中进行的计算。

现在,更大的惊喜是背包测试:

这里的Graal慢了54%!

做一些分析后,我发现我的代码大部分时间都花在了生成用于记忆的键的函数上。

为确保正确,我对集合进行了排序,然后转换为字符串。 这是很多不必要的工作,它依赖于HashSet java实现。

因此,我更改了从中生成密钥的方法:

private fun generateKey(choice: Set<Watch>): String =                 choice.sortedBy { "${it.price}-${it.weight}" }.toString()

对此:

private fun generateKey(choice: Set<Watch>): String =choice.map{ it.hashCode() }.sorted().joinToString("")

新功能更快,因为它可以对Watches的哈希(唯一)进行排序,然后将它们连接到String中。

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

可以为Set创建一个更安全的哈希方法,但是这里的目标不是最大程度地优化算法,而是编写有效且清晰的Kotlin代码。

现在,常见的Kotlin的结果是:

在这里,Graal再次明显比C2快,并且总体而言,新的密钥生成器比以前的实现快得多。

我对这些结果的猜测是,C2已针对典型的Java使用进行了严重优化(使用内部函数等),而Graal擅长于编译惯用的Kotlin所采用的小型方法和轻量级对象。

所有这些都值得进一步研究,但我希望本文能激发更多Kotlin开发人员使用Graal。

如果您对更多类似的帖子感兴趣,请关注我的Twitter帐户@ramtop或查看我的博客

翻译自: https://www.javacodegeeks.com/2018/12/comparing-kotlin-performance-graal-c2.html

kotlin与go性能

kotlin与go性能_比较Kotlin性能与Graal和C2相关推荐

  1. mysql数据库最大性能_数据库Mysql性能优化

    关于本文,笔者参考了一下其他博主的资料,加上个人的认知和理解,先整理如下: 在mysql数据库中,mysql key_buffer_size是对MyISAM表性能影响最大的一个参数(注意该参数对其他类 ...

  2. kotlin 反射java类_关于Kotlin反射中实例化类的问题

    先上java代码: public class TUtil { public static T getT(Object o, int i) { try { return ((Class) ((Param ...

  3. 提高mysql性能_提升MySQL性能值得借鉴的几个简易方法

    提升MySQL性能的几个简易方法,主要用于设计.开发阶段的借鉴.[@more@]1.Carefully choose attribute types and lengths. 仔细选择字段的类型与长度 ...

  4. 比较Kotlin性能与Graal和C2

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

  5. JVM Advent Calendar:将Kotlin性能与Graal和C2进行比较

    首先,让我们谈谈测试方法: 所有 测试 都 在 我的 笔记本 上 运行i7 2.0 Ghz 16 Gb Ubuntu 18.4 和 OpenJdk 11 graal VM 选项: - Xms6g - ...

  6. kotlin 对话框_使用Kotlin的Android警报对话框

    kotlin 对话框 In this tutorial, we'll be discussing Alert Dialogs and implement them in our Android App ...

  7. 安卓开发学习日记第四天番外篇_用Kotlin炒冷饭——越炒越小_莫韵乐的欢乐笔记

    安卓开发学习日记第四天番外篇--用Kotlin炒冷饭--越炒越小 前情提要 安卓开发学习日记第一天_Android Studio3.6安装 安卓开发学习日记第二天_破坏陷阱卡之sync的坑 安卓开发学 ...

  8. kotlin跨平台_探索Kotlin跨平台第1部分

    kotlin跨平台 介绍 (Introduction) Kotlin makes Android development more fun. If you search the web, you'll ...

  9. 医疗器械安全要求检查GB9706.1-2020标准注册检报告_安规性能试验新版GB9706.1-2020风险管理要求

    目录 医疗器械安全要求检查GB9706.1-2020标准注册检报告_安规性能试验 GB9706的内容变化在此不多做赘述,新标实施在即,那么有源医疗器械企业该如何应对呢? 1) 还未完成检测的医疗器械产 ...

最新文章

  1. ecshop /api/client/api.php、/api/client/includes/lib_api.php SQL Injection Vul
  2. 【PMP】项目风险管理~重点知识
  3. python unittest接口测试_python+request+unittest 接口测试练习
  4. B/S----验证方式及练习
  5. Openlayer通过wms请求geoserver加载慢
  6. 用什么软件可以检测苹果耳机芯片_苹果现在要用 AirPods,彻底占据你的耳朵了...
  7. springCloud 之 Eureka高可用配置
  8. LCD1602单片机(STC51/STM32)驱动程序详解
  9. PyQt5 给QLabel添加点击事件
  10. 姿态估计之CPN(Cascaded Pyramid Network)
  11. win10无法访问xp计算机,WinXP无法访问Win10共享文件夹,拒绝访问怎么办?
  12. 入门 Android Lint
  13. 12.Opencv大作业——实现鼠标绘制基本图形
  14. 生产者消费者模型【新版】
  15. VIM编辑器不能wq退出
  16. HTTP 204,304状态码
  17. 创建esp分区和msr分区是做什么用得
  18. C语言实现简单的ai麻将对局(较大工程,持续更新ing)
  19. 为什么要有不同的参考文献格式?
  20. 小程序 zoom_Zoom是否真正监视您在通话中使用的应用程序?

热门文章

  1. 恶意NPM包窃取Discord 令牌和信用卡信息等
  2. 在solidworks中使用全局变量及方程式来进行标注
  3. mysql 外键详解_mysql外键详解
  4. 安徽师范大学数学与计算机科学学院,安徽师范大学数学与计算机科学学院.PPT...
  5. iperf详细介绍~!《转》
  6. C语言库函数中的Strcat函数
  7. for..of的用法
  8. 算法学习二,红黑树查找算法
  9. python设置环境变量path_PYTHONPATH环境变量
  10. 计算机奥林匹克竞赛题库,美国计算机奥林匹克竞赛题库分享