Okapi Project

FastArrayList による List 処理の高速化

バージョン
2003 年 07 月 08 日 Ver.1.0
作成者
T.Itoh ( Xware )

要約

Jakarta Project の提供する Commons ユーティリティの中の Collections に含まれる FastArrayList を使用した結果を示します。

FastArrayList は Java.util.ArrayList クラスの高速版という位置づけで提供されているもので、「マルチスレッドを利用した状態での List からの読み出しが高速化する」 といわれています。ここでは実際に FastArrayList を使ってサンプルのソースを作成して検証を行います。

目次


1.FastArrayList の検証

まず、マルチスレッドを利用しない場合の FastArrayList プログラムを実行します。

import org.apache.commons.collections.*;
import java.util.*;

/**
 * SampleFastArrayList
 *
 * @author titoh
 */
public class SampleFastArrayList {

	public static void main(String[] args){
		new SampleFastArrayList();
	}

	public SampleFastArrayList(){

		// 処理開始時の時間を取得
		long startTime = System.currentTimeMillis();

		// FastArrayList のお試し処理開始
		this.fastArrayList();

		// FastArrayList の処理終了時間を取得
		long fastEndTime = System.currentTimeMillis();

		// FastArrayList の総処理時間を取得
		System.out.println("FastArrayList Exec Time --- = [" + (fastEndTime - startTime) + "]ms");

		// オリジナル処理開始
		this.originalArrayList();

		// オリジナルの処理終了時間を取得
		long originalEndTime = System.currentTimeMillis();

		// オリジナルの総処理時間を取得
		System.out.println("OriginalArrayList Exec Time = [" + (originalEndTime - fastEndTime) + "]ms");
	}

	/**
	 * FastArrayList お試し
	 *
	 */
	private void fastArrayList(){

		FastArrayList fastArrayList = new FastArrayList();

		long sTime = System.currentTimeMillis();

		for(int i = 0; i < 200000; i++){
			fastArrayList.add("AAAAAAAAAAAAAAAAAAAAAAA" + i);
		}

		long eTime = System.currentTimeMillis();
		System.out.println("FastADDTime --------------- = [" + (eTime - sTime) + "]ms");

		// 高速モードへ突入
		// list に値を格納するときは低速モードじゃないと異常に遅いです。
		fastArrayList.setFast(true);

		for(int j = 0; j < fastArrayList.size(); j++){
			String a = fastArrayList.get(j).toString();
		}

		long tTime = System.currentTimeMillis();
		System.out.println("FastGETTime --------------- = [" + (tTime - eTime) + "]ms");
	}


	/**
	 * OriginalArrayList お試し
	 *
	 *
	 */
	private void originalArrayList(){

		ArrayList arrayList = new ArrayList();

		long sTime = System.currentTimeMillis();

		for(int i = 0; i < 200000; i++){
			arrayList.add("AAAAAAAAAAAAAAAAAAAAAAA" + i);
		}

		long eTime = System.currentTimeMillis();
		System.out.println("OriginalADDTime ----------- = [" + (eTime - sTime) + "]ms");

		for(int j = 0; j < arrayList.size(); j++){
			String a = arrayList.get(j).toString();
		}

		long tTime = System.currentTimeMillis();
		System.out.println("OriginalGETTime ----------- = [" + (tTime - eTime) + "]ms");
	}

}



これを実行すると下記のような実行結果を得られます。

[org.apache.commons.collections.FastArrayList の実行結果]
FastADDTime --------------- = [1047]ms
FastGETTime --------------- = [62]ms
FastArrayList Exec Time --- = [1109]ms

[java.util.ArrayList の実行結果]
OriginalADDTime ----------- = [594]ms
OriginalGETTime ----------- = [15]ms
OriginalArrayList Exec Time = [609]ms


マルチスレッドのソースではありませんので、予想通りオリジナルの方が処理が早く終わっています。
次にマルチスレッドを利用した場合のソースを示します。

import org.apache.commons.collections.*;
import java.util.*;

/**
 * Jakarta Project の FastArrayList の検証(2)
 * (マルチスレッド版)
 *
 *
 * @author titoh
 *
 */
//public class SampleFastArrayListMultiThread implements Runnable  {
public class SampleFastArrayListMultiThread extends Thread  {

	public static void main(String[] args){

		// スレッドの生成
		for(int i = 0; i < 1000; i++){
			CrimeThread ct = new CrimeThread();
			ct.start();
		}
	}

}

class CrimeThread extends Thread {

	// 生成されたスレッドで動くやつ
    public void run(){

		// 処理開始時の時間を取得
		long startTime = System.currentTimeMillis();

		// FastArrayList のお試し処理開始
		this.fastArrayList();

		// FastArrayList の処理終了時間を取得
		long fastEndTime = System.currentTimeMillis();

		// FastArrayList の総処理時間を取得
		System.out.println("[" + super.getName() + "F] FastArrayList Exec Time = " + (fastEndTime - startTime));

		// オリジナル処理開始
		this.originalArrayList();

		// オリジナルの処理終了時間を取得
		long originalEndTime = System.currentTimeMillis();

		// オリジナルの総処理時間を取得
		System.out.println("[" + super.getName() + "O] OriginalArrayList Exec Time = " + (originalEndTime - fastEndTime));
    }

	/**
	 * FastArrayList お試し
	 *
	 */
	private void fastArrayList(){

		FastArrayList fastArrayList = new FastArrayList();

		long sTime = System.currentTimeMillis();

		for(int i = 0; i < 500; i++){
			fastArrayList.add("AAAAAAAAAAAAAAAAAAAAAAA" + i);
		}

		long eTime = System.currentTimeMillis();
		//System.out.println("FastADDTime --------------- = [" + (eTime - sTime) + "]ms");

		// 高速モードへ突入
		// list に値を格納するときは低速モードじゃないと異常に遅いです。
		fastArrayList.setFast(true);

		for(int j = 0; j < fastArrayList.size(); j++){
			String a = fastArrayList.get(j).toString();
		}

		long tTime = System.currentTimeMillis();
		//System.out.println("FastGETTime --------------- = [" + (tTime - eTime) + "]ms");
	}


	/**
	 * OriginalArrayList お試し
	 *
	 *
	 */
	private void originalArrayList(){

		ArrayList arrayList = new ArrayList();

		long sTime = System.currentTimeMillis();

		for(int i = 0; i < 500; i++){
			arrayList.add("AAAAAAAAAAAAAAAAAAAAAAA" + i);
		}

		long eTime = System.currentTimeMillis();
		//System.out.println("OriginalADDTime ----------- = [" + (eTime - sTime) + "]ms");

		for(int j = 0; j < arrayList.size(); j++){
			String a = arrayList.get(j).toString();
		}

		long tTime = System.currentTimeMillis();
		//System.out.println("OriginalGETTime ----------- = [" + (tTime - eTime) + "]ms");
	}

}


この実行結果は 1000 多重を起動したものになるため、MS-Excel を利用してグラフ化したものを以下に示します。

FastArrayListとArrayListとの比較のグラフ

局地的に見るとオリジナルの方が速い場合もかなりありますが、スレッドを増やしていくと明らかにオリジナルの方が時間がかかることが上記グラフよりわかります。つまり、スレッドが多くなればなるほど FastArrayList の方が圧倒的に速いと言えますが、スレッド数が 250 程度の場合はオリジナルの方が速いと結論付けられるのではないでしょうか。

Copyright © 2003 - 2006 Okapi Project All Rights Reserved.