Android付属のTimeクラスを使って,GPXファイルに含まれる日時文字列(time要素)の解析を高速化した話.

android.text.format.Timeの利用

地図ロイドにGPXファイルの読み込み処理を実装してパフォーマンスチューニングしていると, GPXファイルに含まれているtime要素の日時文字列
<time>2009-11-03T05:38:46Z</time>
を日時として解析する処理がボトルネックになっていることがわかりました. (GPXの仕様 では,time要素のtimezoneはUTCに決められています)

ここは従来はSimpleDateFormat#parse()を使っていたのですが,AndroidのAPIを漁っていて見つけた Timeクラス のparse3339()メソッドを使うことで,劇的に高速化できました.

以下のテストコードで,2つのメソッドは同じ処理をおこなっています.

  • getParsedTime1 - SimpleDateFormat#parse() 方式
  • getParsedTime2 - Time#parse3339() 方式

実行結果 (HT-03A.数回実行した平均)

方式所要時間
SimpleDateFormat#parse()29秒
Time#parse3339()3秒

速いですねぇ...

public static class TrkPoint {
	String time;

	private SimpleDateFormat sdf;
	private Time androTime;

	public TrkPoint() {
		sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
		sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

		androTime = new Time();
		androTime.switchTimezone("UTC");
	}

	// SimpleDateFormatを使う版
	public long getParsedTime1() {
		try {
			return sdf.parse(time).getTime();

		} catch (ParseException ex) {
			throw new RuntimeException(ex);
		}
	}

	// Android付属Timeを使う版
	public long getParsedTime2() {
		androTime.parse3339(time);
		return androTime.normalize(false);
	}
}

// テストデータの準備
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
String[] timeList = new String[5000];
for (int i = 0; i < timeList.length; i++) {
	timeList[i] = sdf.format(new Date(System.currentTimeMillis() + i*1000));
}

List<Long> dlist = new ArrayList<Long>(timeList.length);

TrkPoint point = new TrkPoint();

// パース処理実行
long t1 = System.currentTimeMillis();

for (String t: timeList) {
	point.time = t;
	long l = point.getParsedTime1();
//	long l = point.getParsedTime2();
	dlist.add(l);
}

// 終了
long t2 = System.currentTimeMillis();

log("elapsed=" + (float)(t2-t1)/1000);


© 2024 KMIソフトウェア