VBCode を Java で実装する
![[Web開発者のための]大規模サービス技術入門 ―データ構造、メモリ、OS、DB、サーバ/インフラ (WEB+DB PRESS plusシリーズ) [Web開発者のための]大規模サービス技術入門 ―データ構造、メモリ、OS、DB、サーバ/インフラ (WEB+DB PRESS plusシリーズ)](http://ecx.images-amazon.com/images/I/51GW5jxmdvL._SL160_.jpg)
[Web開発者のための]大規模サービス技術入門 ―データ構造、メモリ、OS、DB、サーバ/インフラ (WEB+DB PRESS plusシリーズ)
- 作者: 伊藤直也,田中慎司
- 出版社/メーカー: 技術評論社
- 発売日: 2010/07/07
- メディア: 単行本(ソフトカバー)
- 購入: 74人 クリック: 1,779回
- この商品を含むブログ (120件) を見る
はてなほどの規模ではないが、自分も Webサービスを提供する会社に勤めているので、とても興味深く読ませてもらいった。
でも、読むだけだと身にならないので、第6回の演習課題を Java で実装してみることにする。
byte だとキャストをいっぱい書かなきゃいけないので、さぼって計算は int でやってます。
import java.util.LinkedList;
import java.util.List;
public class VBCode {
private static final int MASK = 128;
private VBCode() {
}
/**
* 整数を VBCode にエンコードする。
*
* @param n エンコード対象整数
* @return エンコード結果
*/
public static List<Integer> encode(int n) {
LinkedList<Integer> bytes = new LinkedList<Integer>();
while(true) {
bytes.push(n % MASK);
if (n < MASK) {
break;
}
n = n / MASK;
};
bytes.set(bytes.size() - 1, bytes.peekLast() + MASK);
return bytes;
}
/**
* VBCode を整数にデコードする
*
* @param vb デコード対象
* @return デコード結果
*/
public static int decode(Integer[] vb) {
int n = 0;
for (int i=0; i<vb.length; ++i) {
if (vb[i].intValue() < MASK) {
n = MASK*n + vb[i];
} else {
n = MASK*n + (vb[i] - MASK);
}
}
return n;
}
}で、これを利用してエンコードするコード例が以下。
public class Encode {
public static void main(String[] args) throws IOException {
System.out.println("start");
long start = System.currentTimeMillis();
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("vbcode.bin"));
BufferedReader reader = new BufferedReader(new FileReader("eid_tags.txt"));
String line = null;
while (reader.ready()) {
line = reader.readLine();
String[] vars = line.split("\t");
if (vars.length != 2) {
continue;
}
byte[] tag = vars[0].getBytes();
String nums = vars[1];
List<Integer> vb = new ArrayList<Integer>();
int pre = 0;
for (String s : nums.split(",")) {
int v = Integer.valueOf(s);
vb.addAll(VBCode.encode(v - pre));
pre = v;
}
out.write(tag.length);
out.write(vb.size());
out.write(tag);
for (Integer v : vb) {
out.write(v);
}
}
out.close();
System.out.printf("end (process time = %dms)", System.currentTimeMillis() - start);
}で、これでできたんだけど、実際に サポートページ書籍サポート:[Web開発者のための]大規模サービス技術入門 ―データ構造,メモリ,OS,DB,サーバ/インフラ:|gihyo.jp … 技術評論社 からサンプルデータをダウンロードしてきて実行してみたら、Core2 Duo E7200(2.53GHz)でエンコードに 25〜30秒くらいかかる。
本では Core2 Duo T7200(2GHz)で3秒って書いてあるんですが・・・
ただ、2700万回くらいメソッド呼び出しがあるので、1回あたりの処理時間が 0.001ms だとしても、27秒かかる計算なので、こんなもんだという気もするが・・・うーん、大規模データの扱いは奥が深いな。
時間のあるときプロファイリングでもしてみよっと