Halo, Habr! Mengingat tidak ada berita terbaru tentang kebijakan Oracle tentang perizinan Java, masalah pindah dari versi Oracle ke
OpenJDK menjadi semakin akut. Odanko di OracleLabs telah lama melakukan hal yang sangat keren yang disebut
GraalVM , yang merupakan kompiler
JIT keren yang ditulis di Jawa, serta runtime untuk menjalankan kode dalam bahasa seperti JavaScript, Ruby, Python, C, C ++, Scala, Kotlin, R, Clojure. Mengesankan, bukan? Tapi bukan tentang kesejukan lingkungan polyglot, saya ingin memberi tahu Anda. Kita akan berbicara tentang kesulitan menggabungkan perakitan grail terbaru ke dalam ekosistem OpenJDK 11, dan sedikit tentang kinerja, sedikit ...
Pertama adalah kata
Kisah kenalan saya dengan
graalvm dimulai pada
joker pada tahun 2017. Di sana
Chris Seaton berbicara dengan sangat rinci tentang internal kompiler dan menunjukkan keajaiban kompilasi
AOT menggunakan gambar-asli dari pengiriman grail sebagai contoh (ini adalah lelucon yang mengkompilasi kode Java Anda menjadi biner asli).
Setelah laporan itu, saya berlatih untuk waktu yang sangat lama dalam mengkompilasi biner asli dari proyek kesayangan saya, meletakkan kruk dan garu untuk mendapatkan refleksi di semua tempat (baik itu tidak apa-apa!) Dan akhirnya menemukan masalah yang belum terselesaikan dengan IO (sesuatu di sana tidak lepas landas dengan zookeeper, sekarang saya tidak ingat apa). Meludah saat menggunakan gambar asli :-(
Tahun 2018, semua joker yang sama dan graalvm yang sama dalam laporan super rinci dari Oleg Shelaev tentang AOT.
Dalam laporan dan presentasi, semuanya terlihat sangat keren, dan ada juga proyek hewan peliharaan yang tergeletak di cakram ... saatnya untuk mengungkap terminal, mengayunkan kandidat pelepas grail baru dan bertempur! Kami akan menyentuh jit.
Halo dunia
Menyentuh dan menendang JIT kecil baru (pada saat penulisan artikel ini adalah versi
ce-1.0.0-rc14 ) kami akan menggunakan sepotong kode untuk menguji kinerja dari situs
https://graalvm.org sebagai contoh - contoh pertama kami.
Apa proyek java (bahkan
Hello World ) lakukan tanpa sistem build? Itu benar, hanya javac yang belajar memasak. Javak kita tidak akan belajar memasak, biarkan pakar mengarahkan javak.
Jadi, temui pom.xml:
pom.xml<?xml version="1.0"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>my-app</name> <url>http://maven.apache.org</url> <properties> <java.version>11</java.version> <graalvm.version>1.0.0-rc14</graalvm.version> </properties> <profiles> <profile> <id>jdk11</id> <activation> <jdk>11</jdk> </activation> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.10</version> <executions> <execution> <id>copy</id> <phase>process-test-classes</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/lib</outputDirectory> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>com.mycompany.app.App</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build> </profile> </profiles> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <release>${java.version}</release> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.graalvm.compiler</groupId> <artifactId>compiler</artifactId> <version>${graalvm.version}</version> </dependency> <dependency> <groupId>org.graalvm.truffle</groupId> <artifactId>truffle-api</artifactId> <version>${graalvm.version}</version> </dependency> <dependency> <groupId>org.graalvm.sdk</groupId> <artifactId>graal-sdk</artifactId> <version>${graalvm.version}</version> </dependency> <dependency> <groupId>org.graalvm.js</groupId> <artifactId>js</artifactId> <version>${graalvm.version}</version> </dependency> <dependency> <groupId>org.graalvm.js</groupId> <artifactId>js-scriptengine</artifactId> <version>${graalvm.version}</version> </dependency> </dependencies> </project>
Struktur file proyek terlihat seperti ini:

Kode kelas
com.mycompany.app.App (contoh salin-tempel dari graalvm.org):
App.java package com.mycompany.app; public class App { static final int ITERATIONS = Math.max(Integer.getInteger("iterations", 1), 1); public static void main(String[] args) { String sentence = String.join(" ", args); for (int iter = 0; iter < ITERATIONS; iter++) { if (ITERATIONS != 1) System.out.println("-- iteration " + (iter + 1) + " --"); long total = 0, start = System.currentTimeMillis(), last = start; for (int i = 1; i < 10_000_000; i++) { total += sentence.chars().filter(Character::isUpperCase).count(); if (i % 1_000_000 == 0) { long now = System.currentTimeMillis(); System.out.printf("%d (%d ms)%n", i / 1_000_000, now - last); last = now; } } System.out.printf("total: %d (%d ms)%n", total, System.currentTimeMillis() - start); } } }
Code
module-info.java :
module-info.java module com.mycompany.app {}
Hmm, kosong ... Tapi ini kosong karena saya ingin menunjukkan kepada Anda bagaimana java kustom (tentang custom java sedikit kemudian) akan bersumpah dengan modul yang tidak dideklarasikan yang dibutuhkan aplikasi kita.
Pancake pertama ...
tidak kental Mari kumpulkan proyek kami dan luncurkan. Begini:
mvn clean package
Kami meluncurkan:
$JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -Diterations=10 -jar target/my-app-1.0-SNAPSHOT.jar In 2017 I would like to run ALL languages in one VM.
Ada dua poin penting di sini:
JVMCI adalah hal eksperimental yang telah muncul di Jawa sejak versi 9, jadi kita perlu:
Peluncuran hasil- iterasi 1 - 1 (1466 ms)
2 (461 ms)
3 (463 ms)
4 (138 ms)
5 (151 ms)
6 (159 ms)
7 (266 ms)
8 (128 ms)
9 (144 ms)
total: 69999993 (3481 ms)
- iterasi 2 - 1 (233 ms)
2 (169 ms)
3 (121 ms)
4 (205 ms)
5 (170 ms)
6 (152 ms)
7 (227 ms)
8 (158 ms)
9 (108 ms)
total: 69999993 (1644 ms)
- iterasi 3 - 1 (98 ms)
2 (102 ms)
3 (98 ms)
4 (102 ms)
5 (95 ms)
6 (96 ms)
7 (101 ms)
8 (95 ms)
9 (97 ms)
total: 69999993 (990 ms)
- iterasi 4 - 1 (109 ms)
2 (114 ms)
3 (97 ms)
4 (98 ms)
5 (100 ms)
6 (103 ms)
7 (125 ms)
8 (108 ms)
9 (100 ms)
total: 69999993 (1056 ms)
- iterasi 5 - 1 (98 ms)
2 (100 ms)
3 (105 ms)
4 (97 ms)
5 (95 ms)
6 (99 ms)
7 (95 ms)
8 (123 ms)
9 (98 ms)
total: 69999993 (1010 ms)
- iterasi 6 - 1 (99 ms)
2 (95 ms)
3 (102 ms)
4 (99 ms)
5 (96 ms)
6 (100 ms)
7 (99 ms)
8 (99 ms)
9 (104 ms)
total: 69999993 (993 ms)
- iterasi 7 - 1 (100 ms)
2 (104 ms)
3 (95 ms)
4 (96 ms)
5 (97 ms)
6 (95 ms)
7 (94 ms)
8 (108 ms)
9 (108 ms)
total: 69999993 (1000 ms)
- iterasi 8 - 1 (100 ms)
2 (106 ms)
3 (99 ms)
4 (95 ms)
5 (97 ms)
6 (97 ms)
7 (101 ms)
8 (99 ms)
9 (101 ms)
total: 69999993 (1012 ms)
- iterasi 9 - 1 (105 ms)
2 (97 ms)
3 (98 ms)
4 (96 ms)
5 (99 ms)
6 (96 ms)
7 (94 ms)
8 (98 ms)
9 (105 ms)
total: 69999993 (993 ms)
- iterasi 10 - 1 (107 ms)
2 (98 ms)
3 (99 ms)
4 (100 ms)
5 (97 ms)
6 (101 ms)
7 (98 ms)
8 (103 ms)
9 (105 ms)
total: 69999993 (1006 ms)
Apa yang kita lihat di sini? Dan kita melihat bahwa iterasi pertama adalah yang terpanjang (3,5 detik), JIT ini sedang memanas. Dan kemudian semuanya lebih atau kurang lancar (dalam satu detik).
Tetapi bagaimana jika kita memberi Java versi baru dari grail? Tidak lebih cepat dikatakan daripada dilakukan:
java -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -Diterations=10 --module-path=target/lib --upgrade-module-path=target/lib/compiler-1.0.0-rc14.jar -jar target/my-app-1.0-SNAPSHOT.jar In 2017 I would like to run ALL languages in one VM.
Hasil peluncuran grail segar- iterasi 1 - 1 (1789 ms)
2 (547 ms)
3 (313 ms)
4 (87 ms)
5 (88 ms)
6 (87 ms)
7 (83 ms)
8 (92 ms)
9 (87 ms)
total: 69999993 (3259 ms)
- iterasi 2 - 1 (241 ms)
2 (161 ms)
3 (152 ms)
4 (195 ms)
5 (136 ms)
6 (129 ms)
7 (154 ms)
8 (176 ms)
9 (109 ms)
total: 69999993 (1553 ms)
- iterasi 3 - 1 (109 ms)
2 (103 ms)
3 (113 ms)
4 (172 ms)
5 (141 ms)
6 (148 ms)
7 (111 ms)
8 (102 ms)
9 (101 ms)
total: 69999993 (1211 ms)
- iterasi 4 - 1 (96 ms)
2 (96 ms)
3 (104 ms)
4 (98 ms)
5 (96 ms)
6 (97 ms)
7 (98 ms)
8 (96 ms)
9 (95 ms)
total: 69999993 (972 ms)
- iterasi 5 - 1 (97 ms)
2 (93 ms)
3 (99 ms)
4 (97 ms)
5 (97 ms)
6 (97 ms)
7 (95 ms)
8 (98 ms)
9 (94 ms)
total: 69999993 (965 ms)
- iterasi 6 - 1 (96 ms)
2 (95 ms)
3 (96 ms)
4 (99 ms)
5 (102 ms)
6 (94 ms)
7 (99 ms)
8 (115 ms)
9 (109 ms)
total: 69999993 (1001 ms)
- iterasi 7 - 1 (98 ms)
2 (96 ms)
3 (99 ms)
4 (98 ms)
5 (118 ms)
6 (98 ms)
7 (95 ms)
8 (99 ms)
9 (116 ms)
total: 69999993 (1017 ms)
- iterasi 8 - 1 (95 ms)
2 (99 ms)
3 (99 ms)
4 (106 ms)
5 (101 ms)
6 (101 ms)
7 (93 ms)
8 (97 ms)
9 (108 ms)
total: 69999993 (993 ms)
- iterasi 9 - 1 (102 ms)
2 (95 ms)
3 (97 ms)
4 (125 ms)
5 (94 ms)
6 (101 ms)
7 (100 ms)
8 (95 ms)
9 (96 ms)
total: 69999993 (1008 ms)
- iterasi 10 - 1 (97 ms)
2 (97 ms)
3 (99 ms)
4 (112 ms)
5 (102 ms)
6 (96 ms)
7 (96 ms)
8 (98 ms)
9 (96 ms)
total: 69999993 (988 ms)
Hasilnya, seperti yang kita lihat, tidak jauh berbeda.
Saya lupa. Yah, kami tidak mencoba menjalankan hal yang sama tanpa kompiler JIT baru-ketinggalan jaman. Kami akan melakukan:
java -Diterations=10 -jar target/my-app-1.0-SNAPSHOT.jar In 2017 I would like to run ALL languages in one VM.
Hasil tanpa kompiler JIT bermodel baru- iterasi 1 - 1 (372 ms)
2 (271 ms)
3 (337 ms)
4 (391 ms)
5 (328 ms)
6 (273 ms)
7 (239 ms)
8 (271 ms)
9 (250 ms)
total: 69999993 (2978 ms)
- iterasi 2 - 1 (242 ms)
2 (253 ms)
3 (253 ms)
4 (240 ms)
5 (245 ms)
6 (275 ms)
7 (273 ms)
8 (263 ms)
9 (234 ms)
total: 69999993 (2533 ms)
- iterasi 3 - 1 (237 ms)
2 (235 ms)
3 (234 ms)
4 (246 ms)
5 (242 ms)
6 (238 ms)
7 (244 ms)
8 (243 ms)
9 (253 ms)
total: 69999993 (2414 ms)
- iterasi 4 - 1 (244 ms)
2 (249 ms)
3 (245 ms)
4 (243 ms)
5 (232 ms)
6 (256 ms)
7 (321 ms)
8 (303 ms)
9 (249 ms)
total: 69999993 (2599 ms)
- iterasi 5 - 1 (246 ms)
2 (242 ms)
3 (248 ms)
4 (256 ms)
5 (280 ms)
6 (233 ms)
7 (235 ms)
8 (266 ms)
9 (246 ms)
total: 69999993 (2511 ms)
- iterasi 6 - 1 (292 ms)
2 (368 ms)
3 (339 ms)
4 (251 ms)
5 (267 ms)
6 (259 ms)
7 (289 ms)
8 (262 ms)
9 (357 ms)
total: 69999993 (3058 ms)
- iterasi 7 - 1 (284 ms)
2 (258 ms)
3 (248 ms)
4 (247 ms)
5 (266 ms)
6 (247 ms)
7 (242 ms)
8 (314 ms)
9 (265 ms)
total: 69999993 (2656 ms)
- iterasi 8 - 1 (239 ms)
2 (238 ms)
3 (257 ms)
4 (282 ms)
5 (244 ms)
6 (261 ms)
7 (253 ms)
8 (295 ms)
9 (256 ms)
total: 69999993 (2575 ms)
- iterasi 9 - 1 (273 ms)
2 (243 ms)
3 (239 ms)
4 (240 ms)
5 (250 ms)
6 (285 ms)
7 (266 ms)
8 (285 ms)
9 (264 ms)
total: 69999993 (2617 ms)
- iterasi 10 - 1 (245 ms)
2 (264 ms)
3 (258 ms)
4 (253 ms)
5 (239 ms)
6 (260 ms)
7 (251 ms)
8 (250 ms)
9 (256 ms)
total: 69999993 (2538 ms)
Hasilnya berbeda dan layak.
C2 tidak memberikan optimasi dalam potongan kode - setiap iterasi dengan waktu yang sama.
Graal mampu mengoptimalkan potongan kode dan dalam jangka panjang memberikan peningkatan kinerja yang baik.
Jadi apa
Ini mungkin pertanyaan utama yang perlu Anda tanyakan pada diri sendiri dan orang lain (anggota tim) ketika kami ingin menambahkan fitur baru ke proyek, alat baru, mesin virtual baru, JIT baru ...
Kisah saya, seperti dijelaskan di atas, dimulai dengan Joker 2017, lalu ada upaya panjang untuk menguasai AOT, dan sekarang saya merasakan kelezatan JIT untuk Jawa di Jawa.
Proyek peliharaan pada disk adalah sejenis mesin proses bisnis, di mana proses diambil oleh pengembang aplikasi di UI browser, dan mereka memiliki kemampuan untuk menulis skrip di JS yang akan berjalan di JVM.
Dalam versi Jawa yang akan datang mereka berjanji untuk menghapus nashorn, GraalVM secara bertahap mendekati rilis ...
Nah, jawaban atas pertanyaannya adalah ini:
- kami ingin runtime untuk menjalankan JS (dan tidak hanya)
- ingin kecepatan jit
- kami ingin peluncuran aplikasi proyek hewan peliharaan muncul seperti sebelumnya pada 8-ke (tanpa ada
--module-path
dan --upgrade-module-path
tetapi dengan perakitan grail segar)
Jlink
Dua poin pertama dalam daftar jawaban atas pertanyaan di atas sudah cukup jelas, mari kita bahas yang terakhir.
Faktanya adalah pengembang-admin-devops malas dan tidak suka melakukan pekerjaan ekstra (saya juga suka), mereka mencoba mengotomatisasi semuanya dan mengemasnya menjadi bundel siap pakai yang dapat dijalankan sebagai binar sederhana. Nah, ada masalah, mari kita selesaikan.
Alat yang relatif baru dari dunia Java 9+ hadir untuk membantu kami, dan namanya adalah
jlink . Kami mencoba mengemas aplikasi kami dengan semua lib yang diperlukan dalam satu bundel:
jlink --module-path target/classes:target/lib:$JAVA_HOME/jmods --add-modules com.mycompany.app --launcher app=com.mycompany.app/com.mycompany.app.App --compress 2 --no-header-files --no-man-pages --strip-debug --output test
Berapa banyak parameter dari semua, kami uraikan yang utama:
--module-path target / kelas: target / lib: $ JAVA_HOME / jmods
--add-modules com.mycompany.app
--launcher app = com.mycompany.app / com.mycompany.app.App
- Tes output
Anda dapat bertanya kepada paman Google tentang parameter lain, semuanya ditujukan untuk mengurangi ukuran total bundel.
Mari kita lihat hasilnya:

Di dalam test / bin / app ada sh-script sederhana yang meluncurkan aplikasi kami di Java yang terletak di sebelah aplikasi:
Jalankan
uji / nampan / aplikasi pada C2:
./test/bin/app In 2017 I would like to run ALL languages in one VM.
Hasil- iterasi 1 - 1 (315 ms)
2 (231 ms)
3 (214 ms)
4 (297 ms)
5 (257 ms)
6 (211 ms)
7 (217 ms)
8 (245 ms)
9 (222 ms)
total: 69999993 (2424 ms)
- iterasi 2 - 1 (215 ms)
2 (215 ms)
3 (223 ms)
4 (224 ms)
5 (217 ms)
6 (208 ms)
7 (208 ms)
8 (222 ms)
9 (222 ms)
total: 69999993 (2164 ms)
- iterasi 3 - 1 (206 ms)
2 (226 ms)
3 (234 ms)
4 (211 ms)
5 (212 ms)
6 (213 ms)
7 (210 ms)
8 (245 ms)
9 (223 ms)
total: 69999993 (2216 ms)
- iterasi 4 - 1 (222 ms)
2 (233 ms)
3 (220 ms)
4 (222 ms)
5 (221 ms)
6 (219 ms)
7 (222 ms)
8 (216 ms)
9 (220 ms)
total: 69999993 (2215 ms)
- iterasi 5 - 1 (231 ms)
2 (230 ms)
3 (221 ms)
4 (226 ms)
5 (227 ms)
6 (223 ms)
7 (215 ms)
8 (216 ms)
9 (219 ms)
total: 69999993 (2234 ms)
- iterasi 6 - 1 (227 ms)
2 (218 ms)
3 (221 ms)
4 (254 ms)
5 (222 ms)
6 (212 ms)
7 (214 ms)
8 (222 ms)
9 (222 ms)
total: 69999993 (2241 ms)
- iterasi 7 - 1 (217 ms)
2 (225 ms)
3 (222 ms)
4 (223 ms)
5 (227 ms)
6 (221 ms)
7 (219 ms)
8 (226 ms)
9 (219 ms)
total: 69999993 (2217 ms)
- iterasi 8 - 1 (218 ms)
2 (242 ms)
3 (219 ms)
4 (218 ms)
5 (224 ms)
6 (226 ms)
7 (223 ms)
8 (220 ms)
9 (219 ms)
total: 69999993 (2228 ms)
- iterasi 9 - 1 (234 ms)
2 (218 ms)
3 (217 ms)
4 (217 ms)
5 (225 ms)
6 (222 ms)
7 (216 ms)
8 (226 ms)
9 (214 ms)
total: 69999993 (2212 ms)
- iterasi 10 - 1 (226 ms)
2 (230 ms)
3 (215 ms)
4 (238 ms)
5 (225 ms)
6 (218 ms)
7 (218 ms)
8 (215 ms)
9 (228 ms)
total: 69999993 (2233 ms)
Sekarang di graalvm (dengan mendefinisikan flag yang diperlukan untuk dijalankan dalam variabel
JLINK_VM_OPTIONS ):
Hasil:
Error occurred during initialization of boot layer java.lang.module.FindException: Module jdk.internal.vm.ci not found
Yah, kami tiba ... Dan sekarang ingat bahwa kami bekerja dengan java 11 di lingkungan modular, kami sedang membangun aplikasi sebagai modul, tetapi kami tidak memberi tahu siapa pun tentang modul yang digunakan. Saatnya memperbaikinya.
Versi baru module-info.java:
module com.mycompany.app { requires jdk.internal.vm.compiler; requires org.graalvm.sdk; requires org.graalvm.truffle; requires transitive org.graalvm.js; requires transitive org.graalvm.js.scriptengine; }
Kami mengumpulkan , menghapus direktori pengujian,
tautan .
Hasil:
Error: automatic module cannot be used with jlink: icu4j from file:///home/slava/JavaProjects/graal-js-jdk11-maven-demo/target/lib/icu4j-62.1.jar
Apa jenis "modul otomatis kennote bi uzd"? Dan
tautan ini
memberi tahu kita bahwa
lib icu4j tidak mengandung module-info.class. Apa yang diperlukan agar kelas seperti itu muncul di dalam lib yang ditentukan:
- memahami daftar modul yang digunakan oleh siapa saja dan membuat module-info.java , tentukan semua paket yang harus terlihat dari luar
- kompilasi module-info.java untuk
- letakkan module-info.java yang sudah dikompilasi ke dalam dzharnik
Ayo pergi!
File module-info.java dengan semua isinya akan menghasilkan utilitas
jdeps dari
openjdk -11 untuk kita:

Kami mengkompilasi module-info.java untuk icu4j:

Kami memperbarui dzharnik dengan mendorong
module-info.class ke dalamnya:
$JAVA_HOME/bin/jar uf target/lib/icu4j-62.1.jar -C target/modules module-info.class
Tautkan ,
jalankan .
Hasil- iterasi 1 - 1 (1216 ms)
2 (223 ms)
3 (394 ms)
4 (138 ms)
5 (116 ms)
6 (102 ms)
7 (120 ms)
8 (106 ms)
9 (110 ms)
total: 69999993 (2619 ms)
- iterasi 2 - 1 (166 ms)
2 (133 ms)
3 (142 ms)
4 (157 ms)
5 (119 ms)
6 (134 ms)
7 (153 ms)
8 (95 ms)
9 (85 ms)
total: 69999993 (1269 ms)
- iterasi 3 - 1 (86 ms)
2 (81 ms)
3 (87 ms)
4 (83 ms)
5 (85 ms)
6 (100 ms)
7 (87 ms)
8 (83 ms)
9 (85 ms)
total: 69999993 (887 ms)
- iterasi 4 - 1 (84 ms)
2 (86 ms)
3 (88 ms)
4 (91 ms)
5 (85 ms)
6 (88 ms)
7 (87 ms)
8 (85 ms)
9 (85 ms)
total: 69999993 (864 ms)
- iterasi 5 - 1 (94 ms)
2 (86 ms)
3 (84 ms)
4 (83 ms)
5 (85 ms)
6 (86 ms)
7 (84 ms)
8 (84 ms)
9 (83 ms)
total: 69999993 (854 ms)
- iterasi 6 - 1 (83 ms)
2 (89 ms)
3 (87 ms)
4 (87 ms)
5 (86 ms)
6 (86 ms)
7 (91 ms)
8 (86 ms)
9 (85 ms)
total: 69999993 (865 ms)
- iterasi 7 - 1 (87 ms)
2 (86 ms)
3 (88 ms)
4 (90 ms)
5 (91 ms)
6 (87 ms)
7 (85 ms)
8 (85 ms)
9 (86 ms)
total: 69999993 (868 ms)
- iterasi 8 - 1 (84 ms)
2 (85 ms)
3 (86 ms)
4 (84 ms)
5 (84 ms)
6 (88 ms)
7 (85 ms)
8 (86 ms)
9 (86 ms)
total: 69999993 (852 ms)
- iterasi 9 - 1 (83 ms)
2 (85 ms)
3 (84 ms)
4 (85 ms)
5 (89 ms)
6 (85 ms)
7 (88 ms)
8 (86 ms)
9 (83 ms)
total: 69999993 (850 ms)
- iterasi 10 - 1 (83 ms)
2 (84 ms)
3 (83 ms)
4 (82 ms)
5 (85 ms)
6 (83 ms)
7 (84 ms)
8 (94 ms)
9 (93 ms)
total: 69999993 (856 ms)
Hore! Kami berhasil! Sekarang kami memiliki aplikasi yang dilarang dalam bentuk skrip berjalan dengan Java kami, dengan semua modul yang diperlukan (termasuk graalvm segar), dengan preferensi dan wanita muda.
PS
Java tidak bosan dan memberikan makanan baru untuk pikiran dengan setiap rilis. Coba fitur baru, bereksperimen, berbagi pengalaman. Saya harap saya akan segera menulis artikel tentang bagaimana saya melarang bagian dari proyek peliharaan dengan grail (ada vert.x, asinkronisme dan skrip js akan menarik).
Namun ... ini adalah artikel pertama saya tentang Habré, - tolong, jangan memukul keras.