正式版Java9で文字列の結合の速度を確認する #Java9 #String
これは何?
2017/9/21にJava9が正式にリリースされました。 Java9ではStringのあれこれが変わったと聞いていますが、そんなことはどうでもいいのです。
維持屋にとっては、バージョンアップ後のパフォーマンスがどうなるのか、が重要なのです!!(極論)
前提
これと同じプログラムを使ってテストしました。 qiita.com
@YujiSoftware さんのブログで、VMオプションについて記載されていたのでそれについても試しています。
githubのソースの場所はこちら。 github.com
jmhの起動方法などはこちらにまとめています。 https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/command.txt
テストした端末のスペックなどは以下の通りです。
- Windows10 64bit
- Intel® Core™ i7-2820QM CPU @ 2.30GHz
- メモリは8GM
結果
注釈
- スマホからだと見づらいので、パソコンにするか、横にして画面を広げるか、などをお勧めします。
- Scoreの数字が大きいほど、パフォーマンスがいいと言えます。
半角英字
VM version: JDK 1.8.0_144, VM 25.144-b01
Benchmark Mode Cnt Score Error Units StringLineHankaku.call1StringLine thrpt 10 141.099 ± 1.144 ops/s StringLineHankaku.call2StringConcat thrpt 10 35.888 ± 0.221 ops/s StringLineHankaku.call3StringBuffer thrpt 10 97.689 ± 0.812 ops/s StringLineHankaku.call4StringBuilder thrpt 10 98.916 ± 3.052 ops/s
VM version: JDK 9-ea, VM 9-ea+134(Early Access版)
Benchmark Mode Cnt Score Error Units StringLineHankaku.call1StringLine thrpt 10 90.187 ± 2.961 ops/s StringLineHankaku.call2StringConcat thrpt 10 46.822 ± 3.277 ops/s StringLineHankaku.call3StringBuffer thrpt 10 68.937 ± 2.796 ops/s StringLineHankaku.call4StringBuilder thrpt 10 78.742 ± 2.665 ops/s
VM version: JDK 9, VM 9+181
VM options: なし
Benchmark Mode Cnt Score Error Units StringLineHankaku.call1StringLine thrpt 10 92.795 ± 2.711 ops/s StringLineHankaku.call2StringConcat thrpt 10 27.106 ± 17.205 ops/s StringLineHankaku.call3StringBuffer thrpt 10 53.108 ± 21.248 ops/s StringLineHankaku.call4StringBuilder thrpt 10 62.540 ± 21.275 ops/s
VM options: -XX:-CompactStrings -DCompactStringEnabled=false
Benchmark Mode Cnt Score Error Units StringLineHankaku.call1StringLine thrpt 10 108.819 ± 4.212 ops/s StringLineHankaku.call2StringConcat thrpt 10 50.795 ± 0.952 ops/s StringLineHankaku.call3StringBuffer thrpt 10 56.127 ± 0.568 ops/s StringLineHankaku.call4StringBuilder thrpt 10 104.129 ± 1.707 ops/s
半角数字
VM version: JDK 1.8.0_144, VM 25.144-b01
Benchmark Mode Cnt Score Error Units StringLineNumber.call1StringLine thrpt 10 112.127 ± 34.207 ops/s StringLineNumber.call2StringConcat thrpt 10 71.693 ± 0.270 ops/s StringLineNumber.call3StringBuffer thrpt 10 103.061 ± 1.590 ops/s StringLineNumber.call4StringBuilder thrpt 10 88.149 ± 35.149 ops/s
結果全文
VM version: JDK 9-ea, VM 9-ea+134(Early Access版)
Benchmark Mode Cnt Score Error Units StringLineNumber.call1StringLine thrpt 10 245.689 ± 13.801 ops/s StringLineNumber.call2StringConcat thrpt 10 132.742 ± 9.051 ops/s StringLineNumber.call3StringBuffer thrpt 10 49.300 ± 1.349 ops/s StringLineNumber.call4StringBuilder thrpt 10 52.594 ± 2.545 ops/s
結果全文
VM version: JDK 9, VM 9+181
VM options: なし
Benchmark Mode Cnt Score Error Units StringLineNumber.call1StringLine thrpt 10 187.399 ± 111.698 ops/s StringLineNumber.call2StringConcat thrpt 10 103.961 ± 50.983 ops/s StringLineNumber.call3StringBuffer thrpt 10 33.543 ± 21.675 ops/s StringLineNumber.call4StringBuilder thrpt 10 51.688 ± 0.346 ops/s
結果全文
VM options: -XX:-CompactStrings -DCompactStringEnabled=false
Benchmark Mode Cnt Score Error Units StringLineNumber.call1StringLine thrpt 10 238.952 ± 12.086 ops/s StringLineNumber.call2StringConcat thrpt 10 107.838 ± 3.610 ops/s StringLineNumber.call3StringBuffer thrpt 10 101.667 ± 97.174 ops/s StringLineNumber.call4StringBuilder thrpt 10 177.984 ± 3.698 ops/s
結果全文
全角文字
VM version: JDK 1.8.0_144, VM 25.144-b01
Benchmark Mode Cnt Score Error Units StringLineZenkaku.call1StringLine thrpt 10 141.133 ± 1.504 ops/s StringLineZenkaku.call2StringConcat thrpt 10 36.212 ± 0.202 ops/s StringLineZenkaku.call3StringBuffer thrpt 10 97.025 ± 2.155 ops/s StringLineZenkaku.call4StringBuilder thrpt 10 99.454 ± 1.509 ops/s
VM version: JDK 9-ea, VM 9-ea+134(Early Access版)
Benchmark Mode Cnt Score Error Units StringLineZenkaku.call1StringLine thrpt 10 92.686 ± 0.299 ops/s StringLineZenkaku.call2StringConcat thrpt 10 49.554 ± 0.684 ops/s StringLineZenkaku.call3StringBuffer thrpt 10 56.950 ± 6.474 ops/s StringLineZenkaku.call4StringBuilder thrpt 10 69.917 ± 0.210 ops/s
VM version: JDK 9, VM 9+181
VM options: なし
Benchmark Mode Cnt Score Error Units StringLineZenkaku.call1StringLine thrpt 10 93.176 ± 1.204 ops/s StringLineZenkaku.call2StringConcat thrpt 10 48.488 ± 0.728 ops/s StringLineZenkaku.call3StringBuffer thrpt 10 55.984 ± 6.048 ops/s StringLineZenkaku.call4StringBuilder thrpt 10 63.517 ± 0.586 ops/s
結果全文
VM options: -XX:-CompactStrings -DCompactStringEnabled=false
Benchmark Mode Cnt Score Error Units StringLineZenkaku.call1StringLine thrpt 10 109.511 ± 1.972 ops/s StringLineZenkaku.call2StringConcat thrpt 10 50.061 ± 2.419 ops/s StringLineZenkaku.call3StringBuffer thrpt 10 55.549 ± 0.624 ops/s StringLineZenkaku.call4StringBuilder thrpt 10 104.124 ± 1.103 ops/s
結果全文
まとめ
数値でない場合の結合速度は爆速になるどころか、遅くなっている。
- @YujiSoftware さんのブログを読む限りでは、半角英字は速くなってもいいはずなのだが…テストプログラムの書き方の問題であろうか?
VMオプションを付けると、StringBuilderもStringと同等のパフォーマンスになることがある模様。
- Java9に挙げた結果、パフォーマンスが遅くなって困るときはVMオプションの付与を検討してもいいかも。[要検証]
お願い
- 違う結果が出たよ、というのがありましたらテスト方法含めてどこかにまとめたうえで教えてください。勉強しに行きます。
JasperReportsを使うときのライブラリについて
クラスメソッド様のブログにはいつもお世話になっております。
2013年に出たブログですが、今でもたまにたどり着くこのページ。 依存ライブラリの部分がmavenだと若干古くなっているようなのでメモとして残しておく。
JasperReports LibraryはPDFを出力する場合にitextを利用しますが、この時に依存しているバージョンはLGPLである2.1系の最新バージョンである2.1.7にJasperReportsで独自のパッチを当てた、2.1.7.js2です。このバージョンはMavenのcentral repositoryに存在しないため、Jaspersoftのリポジトリを追加しなければなりません。
最新版(6.4.1)だと itext-2.1.7.js6 がMavenのcentral repositoryに存在するようで、リポジトリの追加は不要。
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>xxxx.yyy</groupId> <artifactId>test1</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>test1</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <javac.target>1.7</javac.target> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/net.sf.jasperreports/jasperreports --> <dependency> <groupId>net.sf.jasperreports</groupId> <artifactId>jasperreports</artifactId> <version>6.4.1</version> </dependency> </dependencies> </project>
このページを参考に依存関係を確認する。
確認結果は以下の通り。
[INFO] xxxx.xxxx:test1:jar:0.0.1-SNAPSHOT [INFO] +- junit:junit:jar:3.8.1:test [INFO] \- net.sf.jasperreports:jasperreports:jar:6.4.1:compile [INFO] +- commons-beanutils:commons-beanutils:jar:1.9.3:compile [INFO] +- commons-collections:commons-collections:jar:3.2.2:compile [INFO] +- commons-digester:commons-digester:jar:2.1:compile [INFO] +- commons-logging:commons-logging:jar:1.1.1:compile [INFO] +- com.lowagie:itext:jar:2.1.7.js6:compile [INFO] | \- org.bouncycastle:bcprov-jdk15on:jar:1.52:compile [INFO] +- org.jfree:jcommon:jar:1.0.23:compile [INFO] +- org.jfree:jfreechart:jar:1.0.19:compile [INFO] +- org.eclipse.jdt.core.compiler:ecj:jar:4.3.1:compile [INFO] +- org.codehaus.castor:castor-xml:jar:1.3.3:compile [INFO] | +- org.codehaus.castor:castor-core:jar:1.3.3:compile [INFO] | +- commons-lang:commons-lang:jar:2.6:compile [INFO] | +- javax.inject:javax.inject:jar:1:compile [INFO] | +- stax:stax:jar:1.2.0:compile [INFO] | | \- stax:stax-api:jar:1.0.1:compile [INFO] | \- javax.xml.stream:stax-api:jar:1.0-2:compile [INFO] +- com.fasterxml.jackson.core:jackson-core:jar:2.1.4:compile [INFO] +- com.fasterxml.jackson.core:jackson-databind:jar:2.1.4:compile [INFO] +- com.fasterxml.jackson.core:jackson-annotations:jar:2.1.4:compile [INFO] +- org.apache.lucene:lucene-core:jar:4.5.1:compile [INFO] +- org.apache.lucene:lucene-analyzers-common:jar:4.5.1:compile [INFO] +- org.apache.lucene:lucene-queryparser:jar:4.5.1:compile [INFO] | +- org.apache.lucene:lucene-queries:jar:4.5.1:compile [INFO] | \- org.apache.lucene:lucene-sandbox:jar:4.5.1:compile [INFO] | \- jakarta-regexp:jakarta-regexp:jar:1.4:compile [INFO] +- org.olap4j:olap4j:jar:0.9.7.309-JS-3:compile [INFO] +- com.google.zxing:core:jar:3.2.1:compile [INFO] \- com.ibm.icu:icu4j:jar:57.1:compile [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 53.129 s [INFO] Finished at: 2017-08-18T10:41:44+09:00 [INFO] Final Memory: 14M/64M [INFO] ------------------------------------------------------------------------
以上。
SXSSFWorkbookの不具合 #apachePoi
知らなかったので再現プログラムを書いてみた。
import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.streaming.SXSSFWorkbook; public class WriteTest { public static void main(String[] args) { String outputFilePath = "out.xlsx"; Workbook book = null; FileOutputStream fout = null; try { book = new SXSSFWorkbook(); Font font = book.createFont(); font.setFontName("MS ゴシック"); font.setFontHeightInPoints((short) 9); CellStyle style = book.createCellStyle(); style.setWrapText(true); Sheet sheet = book.createSheet(); Row row = sheet.createRow(0); Cell cell0 = row.createCell(0); cell0.setCellValue("aaa\r\nbbb"); cell0.setCellStyle(style); Cell cell1 = row.createCell(1); cell1.setCellValue("aaa\rbbb"); cell1.setCellStyle(style); Cell cell2 = row.createCell(2); cell2.setCellValue("aaa\nbbb"); cell2.setCellStyle(style); Cell cell3 = row.createCell(3); cell3.setCellValue("aaa\\nbbb"); cell3.setCellStyle(style); fout = new FileOutputStream(outputFilePath); book.write(fout); } catch (IOException e) { e.printStackTrace(); } finally { try { book.close(); } catch (IOException e) { e.printStackTrace(); } } } }
処理結果はこうなり、A1セルの改行が2回行われていることが確認出来る。
原因となるコードはpoi-ooxml-3.xx.jarの org.apache.poi.xssf.streaming.SheetDataWriter.javaの371行目から379行目の部分。 ※3.17-beta1でも直っていないことを確認した。
// Special characters case '\n': case '\r': if (counter > last) { _out.write(chars, last, counter - last); } _out.write("
"); last = counter + 1; break;
#xa;はxml文書で改行コードを表すらしい。
当面の対応は、\r\nを\r、あるいは\nに置換するしかなさそうだけど、本対応はapacheにバグレポートを書くことだろうなぁ。 githubだったらissueに書けばいいんだろうけど、apache poiはsubversionで活動されているので報告先がわからない…。
というか、SXSSFWorkbookってあまり使われていないのかな。
今日学んだことの覚書
Linuxコマンドメモ<find+grepの組み合わせ>
コマンド
find ./* -newermt '20170803 08:00' | xargs grep 検索ワード
これで2017/8/3の8時以降に更新されたファイルの中から、検索ワードが存在するファイルのみを抽出できる。
参考
Eclipse Oxygenをダウンロードしたい
eclipse.org トップページのDONLOWADを踏むとインストーラがダウンロードされてしまう。
そんなんじゃなくて、従来の色々なバージョンのeclipseが選択できる画面からダウンロードしたいんだ!
そんな人向け。
遷移方法は
トップページを開く
↓
「GETTEING STARTED」 をクリック
↓
「DONLOWAD ECLIPSE IDE」 のボタンをクリック
↓
薄く出ている、「Download Packages」のリンクをクリック
↓
慣れ親しんだページに遷移できる。
"10年の長きに渡り Java の可変長引数を過信していた話"を読んで確認した
恥ずかしながら、自分も過信していたのでこのブログを読んで確認してみた。
public class 可変長引数テスト { public static void main(String... args) { new 可変長引数テスト().method(); new 可変長引数テスト().method("hello"); new 可変長引数テスト().method("hello", "world"); String str = "hello"; new 可変長引数テスト().method(str); str = null; new 可変長引数テスト().method(str); new 可変長引数テスト().method(null); new 可変長引数テスト().method((String) null); new 可変長引数テスト().method((String[]) null); } public void method(String... args) { System.out.println("*-*-*-*-*-"); try { for (String string : args) { System.out.println(string); } } catch (NullPointerException e) { e.printStackTrace(); } } }
eclipseだと、
new 可変長引数テスト().method(null);
この行で以下のような警告文が表示される。(java1.7だと以下の文章)
タイプ null の引数は、タイプ 可変長引数テスト からの可変引数メソッド method(String…) の呼び出しに対しては String へ明示的にキャストする必要があります。あるいは、可変引数呼び出しに対しては String へキャストすることもできます
- コンパイラがこのような警告を吐く記述はちょっと疑うようにした方がいい。
- わかりました、ということでStringに明示的にキャストしても、元の記事にあるようにぬるぽで落ちる。
nullを明示的に渡したいときはStringにキャストしないといけない。
普段意識したことが無かったので、勉強になった。
数年後の自分がこのブログにたどり着くことが無いといいな。