重複のない複数のIPv4アドレスの範囲(startとendのアドレスで示される)から、 指定されたIPv4アドレスが含まれるモノを検索するモジュールです。
$ gradle build
出力: build/libs/ipv4_binsearch-X.X.jar
pom.xml is obsoleted.
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 が返る
}
}
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 版) は以下の点を除き 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の速度に対して有利 に働いていると推測できます。