Bagaimana untuk melaksanakan panggilan bersama dengan Lua dalam kod Java
一、方案
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。
目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的小伙伴欢迎关注下。
目前最常见的方案:luaj,纯Java实现的Lua解析器,基于Lua 5.2
LuaJ的原理:用Java实现了一套Lua的编译器,本质上是把Lua文件中的Lua语言动态编译成了Java字节码,因此会收到诸多限制(比如第三方库的问题),而LuaJ本质上也只是运行在JVM上的Java字节码,和运行在C编译器环境下的Lua是有区别的
Maven pom
虽然源码已有3.0.2版本,但作者未上传maven,如有需要,可以自行导入jar包(源码中已打好3.0.2的jar包)
<dependency> <groupId>org.luaj</groupId> <artifactId>luaj-jse</artifactId> <version>3.0.1</version> </dependency>
二、性能测试
以下我们以最基本的for循环并执行加法操作为例,分别在java外部for一万次,并在lua内部再for一万次
java原生代码
原生代码执行时间:1ms ~ 2ms
private static void runJava(int iterNum) { beg = System.currentTimeMillis(); for (int j = 0; j < iterNum; j++) { int a = 0; for (int i = 0; i < 10000; i++) { a = a + i; } } end = System.currentTimeMillis(); }
lua脚本
function test() a = 0; for i = 0, 10000, 1 do a = a + i; end end
1. ScriptEngine调用方式
调用方式:外部10000次调用,lua内部10000次循环a++ 总时间:8.9s左右 平均一次lua方法调用(1w次a++):0.89ms lua内部一次循环调用(1次a++):0.000089ms 修改lua内部循环1次 时间:10ms 平均一次lua方法调用:0.001ms
// ================================================================================== // ScriptEngine方式 // ================================================================================== Reader reader = new FileReader(luaStr); LuaScriptEngine luaScriptEngine = (LuaScriptEngine) new LuaScriptEngineFactory().getScriptEngine(); // 使用luajc编译器,比默认luac编译器快3倍 LuajContext context = (LuajContext) luaScriptEngine.getContext(); LuaJC.install(context.globals); CompiledScript compiledScript = luaScriptEngine.compile(reader); Bindings bindings = new SimpleBindings(); compiledScript.eval(bindings); LuaFunction luafunc = (LuaFunction) bindings.get("test"); beg = System.currentTimeMillis(); for (int i = 0; i < iterNum; i++) { luafunc.call(); } end = System.currentTimeMillis(); // ==================================================================================
2. Globals调用方式
调用方式:外部10000次调用,lua内部10000次循环a++ 时间:2.3s左右 平均一次lua方法调用:0.23ms lua内部一次循环调用:0.000023ms 修改lua内部循环1次 时间:4ms 平均一次lua方法调用:0.0004ms
// ================================================================================== // Global方式 // ================================================================================== Globals globals = JsePlatform.standardGlobals(); // 使用luajc编译器,比默认luac编译器快3倍 LuaJC.install(globals); LuaValue doFile = globals.get("dofile"); doFile.call(LuaValue.valueOf(luaStr)); LuaValue luaValue = globals.get("test"); beg = System.currentTimeMillis(); for (int i = 0; i < iterNum; i++) { luaValue.call(); } end = System.currentTimeMillis();
1w*1w调用总时间 | 平均一次lua脚本时间 | lua内部一次循环时间 | |
---|---|---|---|
Java | 1ms-2ms | - | - |
ScriptEngine | 8.9s | 0.89ms | 0.000089ms |
Globals | 2.3s | 0.23ms | 0.000023ms |
3. lua调用java
把lua内的循环10000次,挪到java方法执行,java for(10000) -> lua -> java for(10000)
function test() luaTestJava:javaLoop() end
Java提供loop方法
public static void javaLoop() { int a = 0; for (int i = 0; i < 10000; i++) { a = a + i; } }
Global调用方式:5ms ScriptEngine调用方式:30ms
三、结论
luaj没有jit
目前看来,在luaJ这个方案下,Globals的调用方式速度最快
同样的代码,在lua执行和在java执行始终是有差距的,lua执行就是比java执行慢很多 后经过分析源码,发现luaj的每一次++操作,都会new出LuaValue对象,经过dump也发现测试中的LuaValue对象创建非常多
luaJ的实现相对完整,lua和java可以相互调用,相互传参
某些情况下,luajc编译模式的效率和基于C的lua效率差不多源码中的示例
四、其他调用方式?
脱离java环境的lua编译器,lua单独运行进程,提供服务,java跨进程调用服务(没有尝试过,不知道跨进程调用掉率如何,也不知道lua进程资源占用情况) 这样lua可以使用luajit,也不受版本限制(luaJ是5.2)
Atas ialah kandungan terperinci Bagaimana untuk melaksanakan panggilan bersama dengan Lua dalam kod Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Panduan untuk Square Root di Java. Di sini kita membincangkan cara Square Root berfungsi di Java dengan contoh dan pelaksanaan kodnya masing-masing.

Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Panduan untuk Penjana Nombor Rawak di Jawa. Di sini kita membincangkan Fungsi dalam Java dengan contoh dan dua Penjana berbeza dengan contoh lain.

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Panduan untuk Nombor Armstrong di Jawa. Di sini kita membincangkan pengenalan kepada nombor Armstrong di java bersama-sama dengan beberapa kod.

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah
