Skip to content

koron/ipv4_binsearch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

IPv4範囲の二分探査モジュール

重複のない複数のIPv4アドレスの範囲(startとendのアドレスで示される)から、 指定されたIPv4アドレスが含まれるモノを検索するモジュールです。

ビルド方法

$ gradle build

出力: build/libs/ipv4_binsearch-X.X.jar

pom.xml is obsoleted.

サンプルコード

IPv4からの構築

import net.kaoriya.qb.ipv4_binsearch.IPv4Table;

public class Sample {
  public static void Main(String[] args) {
    // 検索用のテーブルを構築する
    IPv4Table<String> t = new IPv4Table();
    t.add(IPv4.fromString("192.168.0.8"),
        IPv4.fromString("192.168.0.15"), "foo");
    t.add(IPv4.fromString("192.168.1.100"),
        IPv4.fromString("192.168.3.200"), "bar");
    t.add(IPv4.fromString("10.0.0.0"),
        IPv4.fromString("10.1.0.0"), "baz");

    // 検索する
    t.find(IPv4.fromString("192.168.0.12")); // "foo" が返る
    t.find(IPv4.fromString("192.168.2.0"));  // "bar" が返る
    t.find(IPv4.fromString("10.0.23.254"));  // "baz" が返る

    t.find(IPv4.fromString("0.0.0.0"));       // null が返る
    t.find(IPv4.fromString("9.255.255.255")); // null が返る
    t.find(IPv4.fromString("10.1.0.1"));      // null が返る
    t.find(IPv4.fromString("127.0.0.1"));     // null が返る
  }
}

CIDR/サブネット形式からの構築

import net.kaoriya.qb.ipv4_binsearch.CIDR;

// ...中略...

IPv4Table<String> t = new IPv4Table();
// CIDR形式
t.add(CIDR.fromString("192.168.0.8/24"), "foo");
// サブネット形式
t.add(CIDR.fromString("192.168.1.0/255.255.255.0"), "foo");

IPv4Table2 (off-heap 版)の使い方

IPv4Table2 (off-heap 版) は以下の点を除き IPv4Table と同じように使えます。

  • IPv4Table2 作成後の要素追加 (add) はできない
    • 必要に応じて off-heap メモリの破棄 (close) はできる
  • 構築済みの IPv4Table から変換して作成する

つまり一旦 IPv4Table を作成・各要素を追加・構築してから、 それを元に IPv4Table2 を作成してください。 また一度作成したIPv4Table2 は変更できません。 add() メソッドの呼び出しは UnsupportedOperationException で失敗します。

IPv4Table2 の作成例:

IPv4Table<String> t = new IPv4Table();
// TODO: IPv4Table t の構築

IPv4Table2<String> t2 = new IPv4Table2(t,
        new SerializableConverter<String>());

IPv4Table2 を作成する時には IPv4Table の他に Converter が必要です。 独自の Converter を実装することもできますが、 予め以下の2種類の Converter が実装されています。

種類 説明
SerializableConverter java.io.Serializable を実装したクラスを変換できる Converter。比較的手軽に利用できるが、速度やメモリ効率はあまり良くない。
MessagePackableConverter org.msgpack.MessagePackable を実装したクラスを変換できる Converter。実装の手間はあるが、速度やメモリ効率は比較的良くできる。

上述の例は SerializableConverter を用いたものでした。 以下には MessagePackableConverter を用いた実装例を示します。

public class Value implements MessagePackable {
    private String stringProperty;
    public Value() { } // 引数なしコンストラクタが必須
    public Value(String stringValue) {
        this.stringProperty = stringValue;
    }
    public String getStringProperty() {
        return this.stringProperty;
    }
    public void setStringProperty(String value) {
        this.stringProperty = value;
    }

    // MessagePackable インターフェースの実装

    public void readFrom(Unpacker unpacker) throws IOException {
        this.stringProperty = unpacker.readString();
    }
    public void writeTo(Packer packer) throws IOException {
        packer.write(this.stringProperty);
    }
}

// 中略

IPv4Table<Value> t = new IPv4Table();
// TODO: IPv4Table t の構築

IPv4Table2<Value> t2 = new IPv4Table2(t,
        new MessagePackableConverter<Value>(Value.class));

ベンチマーク

実行と結果

ベンチマークを実行するには、以下のようにします。

$ gradle benchmark

以下の様な結果を得られます。

:benchmark1
Benchmark1 executing:

benchmark query IPv4Table in 10 sec: 1685574.80/sec (total 16855748)
benchmark query IPv4Table2 (off-heap) in 10 sec: 1245846.40/sec (total 12458464)
benchmark query IPv4Table2 (heap) in 10 sec: 1147486.20/sec (total 11474862)

Benchmark#1 results:
    off-heap/objects ratio:   73.91%
    heap/objects ratio:       68.08%
    heap/off-heap ratio:      92.10%
:benchmark3
Benchmark3 executing:

Many objects
[    0.651304s] GC: init
[    9.096094s] Generate table
[    5.610543s] GC: after generating
Total: 14.71
Few objects (off-heap)
[    0.010873s] GC: init
[   12.673108s] Generate table
[    0.078269s] GC: after generating
Total: 12.75
Few objects (heap)
[    0.223094s] GC: init
[   11.429514s] Generate table
[    2.187207s] GC: after generating
Total: 13.62

Benchmark#3 results:
    off-heap/objects ratio:   86.70%
    heap/objects ratio:       92.59%
    heap/off-heap ratio:     106.79%

考察

benchmark1 は IPv4Table と IPv4Table2 (off-heap/heap) に対するクエリ回数(速度) を比較するもので、10秒間で何回クエリできたかを示しています。

Benchmark#1 results:
    off-heap/objects ratio:   73.91%
    heap/objects ratio:       68.08%
    heap/off-heap ratio:      92.10%

特に上記は、IPv4Table2 (off-heap) におけるクエリ回数は IPv4Table の約 73% であ ること、また IPv4Table2 (heap) へのクエリ回数は IPv4Table2 (heap) の約 92% であ ることを示しています。

benchmark3 は IPv4Table と IPv4Table2 (off-heap/heap) の再作成にかかる時間を、 GCを含めて計測比較したものです。

Benchmark#3 results:
    off-heap/objects ratio:   86.70%
    heap/objects ratio:       92.59%
    heap/off-heap ratio:     106.79%

特に上記は、IPv4Table2 (off-heap) を使っている(メモリ上に保持している)場合に、 テーブルの再作成にかかる時間が IPv4Table を使っている場合の約 87% であることを 示しています。

off-heap と heap を比べると、主にGCにかかる時間のためにoff-heapの方が速くなりま す。

結論

IPv4Table2 を使うことで、IPv4Tableを使う場合に比べてクエリ速度はやや遅くなるも のの、GCにかかる時間は飛躍的に短くなることがわかります。

また IPv4Table2 (off-heap) のほうが IPv4Table2 (heap) よりも主にGCが理由で速い ことから、ヒープ上に持つオブジェクトのサイズが小さいことがGCの速度に対して有利 に働いていると推測できます。

About

Binary search of IPv4 ranges

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published