java.util.Scannerは遅いですか?

android java
java.util.Scannerは遅いですか?

Androidアプリケーションでは、Scannerクラスを使用して、テキストファイルからfloatのリストを読み取ります(OpenGLの頂点座標のリストです)。 正確なコードは次のとおりです。

Scanner in = new Scanner(new BufferedInputStream(getAssets().open("vertexes.off")));
final float[] vertexes = new float[nrVertexes];
for(int i=0;i

ただし、これは非常に遅いようです(10,000個の浮動小数点数を読み取るのに30分かかりました!)-2.1エミュレータでテストされています。 どうしたの? ScannerをPCで使用したとき、それほど遅いことを覚えていません(以前は100個を超える値を読み取ったことがなかったと言われています)。 それとも、アセット入力ストリームからの読み取りなど、他の何かですか?

助けてくれてありがとう!

  16  4


ベストアンサー

他のポスターが述べているように、データをバイナリ形式で含める方が効率的です。 ただし、簡単な修正のために、次のものを置き換えることがわかりました:

scanner.nextFloat();

with

Float.parseFloat(scanner.next());

ほぼ7倍高速です。

この回答にさらに情報を追加するために、このメソッドのパフォーマンスの問題の原因は、正規表現を使用して次のフロートを検索することです。これは、読んでいるデータの構造を事前に知っている場合は不要です。

(すべてではないにしても)ほとんどの `next *`は同様の理由で正規表現を使用しているため、データの構造がわかっている場合は、常に `next()`を使用して結果を解析することをお勧めします。 I.E. また、「Double.parseDouble(scanner.next())」と「Integer.parseInt(scanner.next())」を使用します。

関連ソース:https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/util/Scanner.java

21


Androidについては知りませんが、少なくともJavaSEでは、スキャナーは遅いです。

内部的に、スキャナーはUTF-8変換を行います。これは、floatを含むファイルでは役に立ちません。

ファイルからfloatを読み取るだけなので、java.ioパッケージを使用する必要があります。

http://www.spoj.pl [SPOJ]のメンバーはI / O速度と格闘しています。 これは非常に難しい問題を抱えたポーランドのプログラミングコンテストサイトです。 それらの違いは、他のサイトよりも幅広いプログラミング言語を受け入れ、多くの問題では、入力が非常に大きいため、効率的なI / Oを記述しないと、プログラムは時間制限を破ります。

カスタムパーサーのアイデアについては、http://www.spoj.pl/forum/viewtopic.php?f = 43&t = 4864&sid = 9b0ab81b86c28738e83e86a43a59d7c6 [こちら]などのフォーラムを確認してください。

もちろん、独自のフロートパーサーを作成することをお勧めしますが、速度が必要な場合でも、それは解決策です。

8


Spotify Challengeのために、彼らはIOをより速く解析するための小さなjavaユーティリティを作成しました:http://spc10.contest.scrool.se/doc/javaioこのユーティリティはhttp://spc10.contest.scrool.se/doc/src/と呼ばれますKattio.java [Kattio.java]。BufferedReader、StringTokenizer、およびInteger.parseInt / Double.parseDouble / Long.parseLongを使用して数値を読み取ります。

2


非常に洞察に満ちた投稿。 通常、Javaで作業したときは、PCで「スキャナー」が最速だと思っていました。 Androidの `AsyncTask`で* WORST *で使用しようとすると同じです。

Androidはスキャナーに代わるものを考え出す必要があると思います。 私は scanner.nextFloat();`と `scanner.nextDouble();& `scanner.nextInt();`を一緒に使用していたため、私の人生はうんざりしていました。 アプリのトレースを行った後、犯人が隠れていることがわかりました。

同様に、 Float.parseFloat(scanner.next());`に変更しました `Double.parseDouble(scanner.next());& `Integer.parseInt(scanner.next());`アプリは非常に高速で、同意する必要があり、* 60%*速くなる可能性があります。

誰もが同じことを経験している場合は、ここに投稿してください。 そして、私は「スキャナー」APIの代替案にも目を光らせています。優れたアイデアを持っている人なら誰でも前に出て、ファイル形式の読み取りについてここに投稿することができます。

1


はい、私はこのようなものを見ていません。 この方法でデスクトップ上で4秒で約10Mの浮動小数点数を読むことができますが、それほど違いはありません。

私は他の説明を考えています-getAssets()から入力ストリームを読み取る際におそらくブロックしていますか? そのリソースを完全に読んで、タイミングを計ってから、スキャンにどれくらいの時間がかかるかを確認することができます。

0


「スキャナー」は問題の一部かもしれませんが、知るためにはコードをプロファイリングする必要があります。 代替手段のほうが速い場合があります。 これは、単純なhttps://stackoverflow.com/questions/2080403/how-can-i-handle-it-with-scanner-java/2082174#2082174 [ベンチマーク]で「Scanner」と「StreamTokenizer」を比較したものです。

0


私はまったく同じ問題を抱えていました。 18 KBのファイルを読み取るのに10分かかりました。 最後に、DataOutputStreamを使用して、人間が読み取れる数値を機械が読み取れる形式に変換するデスクトップアプリケーションを作成しました。

結果は驚くべきものでした。

ところで、私がそれをトレースしたとき、ほとんどのScannerメソッド呼び出しには正規表現が含まれ、その実装は `com.ibm.icu。**`パッケージ(IBM ICUプロジェクト)によって提供されます。 本当にやり過ぎです。

String.formatについても同様です。 Androidでは避けてください!

0


タイトルとURLをコピーしました