最近も時々Coherence関連をやっています。そんな中、久々のJavaコード。
CoherenceではPOF形式を使うのが当たり前って感じですが、サイズの見積もりとか難しかったりしますね。
ということで、POF形式のオブジェクトのキャッシュ上のサイズをしりたい。
しかも、Coherenceノードとか立てずにスタンドアロンで
しかも、極力汎用的に
という要望にお応えしようとPofのサイズを見積もるための汎用ユーティリティーを作ってみました。
しかも、coherence.jar以外は(pof-config.xmlすらも)いらないようにしました。
mainはこんな感じ。
1.キャッシュに乗せるPojosを作って、
2.ぽふサイズエスティメーターっていう後述のオブジェクト作って、
3.ぽふサイズ取る
簡単ですね!
ExampleMain.java
package com.example.coherence; import java.util.Date; public class ExampleMain { public static void main(String[] args) throws Exception { Person p = new Person("yamamoto dai",34,new Date()); PofSizeEstimater estimater = new PofSizeEstimater(p,PersonSerializer.class); System.out.println(estimater.estimate().getPofSize()); } }
キャッシュに乗せたいオブジェクトはふつうのオブジェクト。
Person.java
package com.example.coherence; import java.io.Serializable; import java.util.Date; public class Person implements Serializable{ public Person() { } public Person(String name, int age, Date birth) { super(); this.name = name; this.age = age; this.birth = birth; } private String name; private int age; private Date birth; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } }
Pofシリアライザ―は、以下。(このあたりはcoherenceのマニュアル参照ください。)
Pojosがでかくなると面倒だけどそんなに難しいコードじゃない。
PersonSerializer.java
package com.example.coherence; import java.io.IOException; import com.tangosol.io.pof.PofReader; import com.tangosol.io.pof.PofSerializer; import com.tangosol.io.pof.PofWriter; public class PersonSerializer implements PofSerializer{ @Override public Object deserialize(PofReader pofreader) throws IOException { int i = 0; Person p = new Person(); p.setName(pofreader.readString(i++)); p.setAge(pofreader.readInt(i++)); p.setBirth(pofreader.readDate(i++)); pofreader.readRemainder(); return p; } @Override public void serialize(PofWriter pofwriter, Object obj) throws IOException { int i = 0; Person result = (Person)obj; pofwriter.writeString(i++, result.getName()); pofwriter.writeInt(i++, result.getAge()); pofwriter.writeDate(i++, result.getBirth()); pofwriter.writeRemainder(null); } }
今回のツールの本体は、以下のソース。
pof-config.xmlとか動的に生成しちゃってるところがみそ。
PofSizeEstimater.java
package com.example.coherence; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.Serializable; import com.tangosol.io.WrapperBufferOutput; import com.tangosol.io.WriteBuffer.BufferOutput; import com.tangosol.io.pof.ConfigurablePofContext; import com.tangosol.io.pof.PofSerializer; import com.tangosol.run.xml.SimpleElement; import com.tangosol.run.xml.XmlElement; public class PofSizeEstimater { private Object target; private XmlElement xml; private byte[] pofBinary; public XmlElement getConfigXml() { return xml; } public byte[] getPofBinary() { return pofBinary; } public int getPofSize(){ return this.pofBinary.length; } public PofSizeEstimater(Serializable o ,Class<? extends PofSerializer> s) throws IOException{ this(o,s,10001); } public PofSizeEstimater(Serializable o ,Class<? extends PofSerializer> s,int typeId) { target = o; // Pofコンフィグファイルを動的生成 this.xml = new SimpleElement("pof-config"); XmlElement elem1 = xml.addElement("user-type-list"); XmlElement elem2 = elem1.addElement("user-type"); elem2.addElement("type-id").setInt(typeId); elem2.addElement("class-name").setString( target.getClass().getCanonicalName()); elem2.addElement("serializer").addElement("class-name").setString(s.getCanonicalName()); } public PofSizeEstimater estimate() throws IOException{ // POFコンフィグからコンテキストを生成 ConfigurablePofContext ctx = new ConfigurablePofContext(xml); // POFバイナリを書き出し ByteArrayOutputStream baos = new ByteArrayOutputStream(); BufferOutput bo = new WrapperBufferOutput(new DataOutputStream(baos)); ctx.serialize(bo , target); this.pofBinary = baos.toByteArray(); bo.close(); return this; } }
実行結果
上記のサンプルを実行すると。
29
って出てくる。29バイトに直列化されたわけだ。
じゃあふつうのJava Serializeは?って疑問になったので、もうちょっと作る。
こんな感じのメソッドをエスティメーターにつけてみた。
public int getJavaSerializeBinarySize() throws IOException{ ByteArrayOutputStream boas_nomal = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(boas_nomal); oos.writeObject(target); int ret = boas_nomal.size(); oos.close(); return ret; }
すると、同じオブジェクトのシリアライズ後のサイズは以下の通り。
171
POFだとすごく小さくなりますね。