HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

org.w3c.util.UUIDとjava.util.UUID

ユニークなIDを生成するための手段として、org.w3c.util.UUID、またJava 5からはjava.util.UUIDがある、というのはいまさらな話。
org.w3c.util.UUIDでは、以下のような文字列が生成される。

<(1)とあるObjectのhashCode(16進)>-<(2)現在時刻(ミリ秒)(16進)>-<(3)IPアドレスのMD5値>

このうち、(1)と(3)はstaticフィールドに保持された値を使用するので、生成されるUUIDで共通。
一方、java.util.UUIDの方はちゃんと追いきれてない。ハイフンで区切られた5個のコンポーネントからなることだけは分かった。JavaDocによると、「ISO/IEC 11578:1996」とかを参照せよ、ということだけど。

で、ふと、org.w3c.util.UUIDのソースを見てみたら、コンストラクタの中で同期用のObjectでsynchronizedしている上に最大10ミリ秒sleepしている。こりゃ、コストがかかりそうだな、ということで(謎)。

まず、org.w3c.util.UUIDの準備。
以下をダウンロード。

で、コンパイルとJARファイル生成。SunのJDK(1.5.0_11)を使用。

javac -encoding UTF-8 -d . -g:none org/w3c/tools/crypt/Md5.java org/w3c/util/UUID.java
jar cvf uuid.jar org/w3c/util/UUID.class org/w3c/tools/crypt/Md5.class

次に測定用のソース。

public class Main {

    public static void main(String[] args) {
        System.out.println("-- 初期化にちょっと時間がかかるようなので一度呼び出しておく。");
        test1(1);
        test2(1);

        System.out.println("-- 初期化さえされてしまえば、一度の呼び出しは大してコストにならない。");
        test1(1);
        test2(1);

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("-- さて、本番‥");
        int N = 1000;
        test1(N);
        test2(N);
    }

    private static void test1(int n) {
        long start = System.currentTimeMillis();
        try {
            for (int i = 0; i < n; ++i) {
                org.w3c.util.UUID uuid = new org.w3c.util.UUID();
                uuid.toString();
            }
        } finally {
            long end = System.currentTimeMillis();
            System.out.printf("    %-20s: %8d ms\n", "org.w3c.util.UUID", (end - start));
        }
    }

    private static void test2(int n) {
        long start = System.currentTimeMillis();
        try {
            for (int i = 0; i < n; ++i) {
                java.util.UUID uuid = java.util.UUID.randomUUID();
                uuid.toString();
            }
        } finally {
            long end = System.currentTimeMillis();
            System.out.printf("    %-20s: %8d ms\n", "java.util.UUID", (end - start));
        }
    }

}

で、実行結果。

-- 初期化にちょっと時間がかかるようなので一度呼び出しておく。
    org.w3c.util.UUID   :      124 ms
    java.util.UUID      :       92 ms
-- 初期化さえされてしまえば、一度の呼び出しは大してコストにならない。
    org.w3c.util.UUID   :        0 ms
    java.util.UUID      :        0 ms
-- さて、本番‥
    org.w3c.util.UUID   :    10187 ms
    java.util.UUID      :       31 ms

まぁ、org.w3c.util.UUIDの方は、生成間隔が10ms以上になるようにsleepしているから、当然といえば当然の結果。
しかし、これだけ差が出るとなると、十分に置き換えの理由になるな。