Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

ByteBufferの処理速度について

自分の理解が間違っているかもしれませんが、ByteBufferを用いるとjavaヒープメモリを通さずにネイティブメモリでデータの読み書きがされるため、通常の配列より処理が速いと聞きました。
それが本当かを検証するため以下のソースを実行してみました。

import java.nio.ByteBuffer;
public class A{
    public static void main(String[] args){
        byte b;
        long startTime = System.nanoTime();
        byte[] array = new byte[100];
        System.out.println("配列 生成時間: "+(System.nanoTime() - startTime));
        startTime = System.nanoTime();
        for(int i=0;i<100;i++){
            array[i] = (byte)i;
        }
        System.out.println("配列 要素追加時間: "+(System.nanoTime() - startTime));
        startTime = System.nanoTime();
        for(int i=0;i<100;i++){
            b = array[i];
        }
        System.out.println("配列 要素読取時間: "+(System.nanoTime() - startTime));
        startTime = System.nanoTime();
        ByteBuffer buffer = ByteBuffer.allocateDirect(100);
        System.out.println("バッファー 生成時間: "+(System.nanoTime() - startTime));
        startTime = System.nanoTime();
        for(int i=0;i<100;i++){
            buffer.put((byte)i);
        }
        System.out.println("バッファー 要素追加時間: "+(System.nanoTime() - startTime));
        startTime = System.nanoTime();
        buffer.flip();
        for(int i=0;i<100;i++){
            b = buffer.get();
        }
        System.out.println("バッファー 要素読取時間: "+(System.nanoTime() - startTime));
    }
}

----------実行結果------------
配列 生成時間: 46014
配列 要素追加時間: 8579
配列 要素読取時間: 7455
バッファー 生成時間: 459410
バッファー 要素追加時間: 54254
バッファー 要素読取時間: 48782
------------------------------

明らかにByteBufferの方が遅いという結果が出てしまいました。。。
これはなぜなのか?それ以前に自分の認識違いやソースに間違いがあったのか?
理由が分かる方、ご教授していただけませんか。

15

回答

10863

閲覧

15件の回答

評価

0

まず、最近のJavaのメモリ管理は結構高速だよ。
ヒープよりヒープ外のほうが速いなんてこともないだろう。

http://sugarpot.sakura.ne.jp/yuno/?Java%2FBufferBenchmark

たくさん比較してる人がいた。

put(byte)じゃなくてput(byte[])が速いんじゃないかなとも思う。
単純にループして書き込むだけだと、恩恵に預かれないんじゃないかなあ。

評価

0

ヒープメモリって何ですか?
JAVAがOSから起動時に確保するメモリ領域は、多めにとって、javaが管理していると思うのですが、この領域に付けられている名前って何ですか。
また、他のプログラムとデータのやり取りが発生する時は、例えばネットワークインターフェースカードからもらった通信データとかはOSが持っていると思うのですが、これをもらってくる時にアクセスするメモリ領域煮付けられている名前って何ですか。

評価

0

>まず、最近のJavaのメモリ管理は結構高速だよ。
ヒープよりヒープ外のほうが速いなんてこともないだろう。

やっぱり、自分の理解が間違ってましたか...
今まではガベージコレクタあるし。とか思ってましたが、メモリ管理についてももっと勉強しようと思います。

>put(byte)じゃなくてput(byte[])が速いんじゃないかなとも思う。
単純にループして書き込むだけだと、恩恵に預かれないんじゃないかなあ。

参考サイト見てみました。put(byte[])のほうが、3倍近く速いですね。

>ヒープメモリって何ですか?

合っているかは定かではないですが。
宣言した変数やオブジェクトを後入れ先出し(LIFO)方式で「メモリアドレス」と「値」のペアで詰んでいく領域だと自分は理解しています。

評価

0

ガベージコレクションは二種類あるので、それも調べてみるといいかも。

評価

0

スタックって、ヒープメモリに同じということですかねぇ。
クラス間無限ループ作って実行すると、確かにスタックエラーになりますし。これって、ガベッジコレクターに清掃されないので、エラーになるんでしょうか。
オブジェクトって、実際はオブジェクトの元クラス@シリアルで情報を管理しているので、どこかでガベッジコレクターがこれを扱っているけど、何処に実装があるのか分かりません。
ご存知でしたら、ぜひご教授ください。

評価

0

一度でも用語でぐぐってみた?

評価

0


>ガベージコレクションは二種類あるので、それも調べてみるといいかも。

>2010-11-10 20:27の意味がやっと理解できました。

「Scavenge GC」と[Full GC]のことですね。
オブジェクトは New, Old, Permanent のメモリ領域で管理されいる。
オブジェクトは生成時にNew領域に格納されて、その中で使用頻度が高いオブジェクトが破棄されずOld領域に格納される。Permanent領域にはクラス、メソッドが格納されて、これだけはヒープ外メモリ。
Scavenge GCはNew領域、Full GCはOldとPermanent領域を最適化する。Scavenge GCは処理時間が短い。対して、Full GCは処理時間長い上にプログラムが一旦停止すると。
つまり、Permanent領域がヒープ外メモリだから、重いFull GCを呼んでしまうことになりかねないということですね。

評価

0

何を?

評価

0

JAVAのゴミって、参照がなく利用されないクラスのことだと思っていました。個人的にはオブジェクトは使わないと消されるけど、クラスはロードしたきり。消す作業がないのが疑問なくらいで。。。
実際は、Permanent領域にいて、クラスも掃除されていたんですかぁ。システムクラスローダのロードクラスは、消すことはできず、URLクラスローダなどでの、自前ロードクラスしか、しかも一斉にしか消せないと思っていました。

評価

0

JAVAのゴミって、参照がなく利用されない×クラス○オブジェクトのことだと思っていました。

評価

0

今のJavaは、基本的に予め確保したヒープから要求されたサイズの領
域を切り出す程度のシンプルかつ高速な管理になってるらしい。
ヒープ外領域はその時点でメモリ管理が複雑なOSに依頼して切り出
してもらうから、確保と解放が重そう。
実アクセス速度は同一でアドレス計算に大きな違いがあるとも思えな
いので、やはりアクセスコードへのオーバーヘッドだろうか。

なお、オブジェクトへのポインタとプリミティブはスタックに静的
(コンパイル時)に確保されるから、実行時に確保するステップがほ
とんどない。

評価

0

コンパイル時に確保って言い方はおかしいな。
コンパイル時に確保するサイズが決まって、実行時にはそのサイズ分
だけスタックポインタがずらされる(たいてい引き算)だけ。

評価

0

> オブジェクトへのポインタとプリミティブはスタックに静的に確保される

もうちょっと正確に言うと、仮引数とローカル変数のプリミティブ型とオブジェクト変数がスタックに積まれますね。メンバ変数は、プリミティブ型であってもヒープに格納されます。(メンバなんだから当たり前だけどね。念のため。)

評価

0

フォローthx。

評価

0

Javacした状態のバイトコードは、BCELなどでソースコードからクラスデータ形式のデータ配列にされて、メモリに保有されますよね。そっちのコードがスタックされている状態の場所とCPUにいれて、順番に処理するという実行可能状態のメモリにスタックされている状態とが想像できるのですが、(あくまで予想)、どっちの場合のスタックなのですか。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。