JAVAのマーカーインターフェースとアノテーション
非キャッシュの仕組み
弊社のシステムはJAVA + strutsで実装されている所が多いのですが、サイト上のページはアクセスの負荷に耐えられるように、WEBサーバーやAPPサーバーから、キャッシュされた情報を返すようにシステムを構築しています。
ただ、ページによっては毎回Actionを実行して、リアルタイムなデータを表示する必要があります。そのために、Actionが特定のマーカーインターフェースかアノテーションを実装していたら、HTTPレスポンスヘッダに
Cache-Control: no-store
Pragma: no-cache
を出力するようにしようと考えました。
疑問点
やりたい事はマーカーインターフェースでもアノテーションでも可能なのですが、実装するにはリフレクション的な事を行うので、どのやり方が一番処理が軽いのか、疑問が浮かびました。
interfaceを実装しているかどうかを調べる方法も、instanceofを使う方法とClass.isAssignableFromを使う方法があるので、それに関しても検証してみたいと思います。
やってみる
で、疑問点を解消するために、実際に実験をしてみました。
- interface
マーカーインターフェースなので、中身は無いです。
public interface NoCacheInterface { }
- annotation
リフレクションするので、RetentionPolicyはRUNTIMEです。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface NoCache { }
- Actionクラス
マーカーインターフェースとアノテーションを実装します。
BaseActionはstrutsのActionを継承して、前/後処理(そこでHTTPレスポンスヘッダの出力も行う)等を行います。
この実験では特に意味は無いですが…。
@NoCache public class TestAction extends BaseAction implements NoCacheInterface {
- 検証コード
それぞれのやり方でぐるぐるループさせます。
処理の前にgcをして、後に残っているメモリ量も見てみます。
TestAction action = new TestAction(); int count = 100000000; long start = 0; -- インターフェース(instanceof) System.gc(); start =System.currentTimeMillis(); for(int i=0;i<count;i++){ if(action instanceof NoCacheInterface){ } } System.out.println((System.currentTimeMillis()-start)+"msec"); System.out.println(Runtime.getRuntime().freeMemory()); -- インターフェース(isAssignableFrom) System.gc(); start =System.currentTimeMillis(); for(int i=0;i<count;i++){ if(NoCacheInterface.class.isAssignableFrom(action.getClass())){ } } System.out.println((System.currentTimeMillis()-start)+"msec"); System.out.println(Runtime.getRuntime().freeMemory()); -- アノテーション System.gc(); start =System.currentTimeMillis(); for(int i=0;i<count;i++){ if(action.getClass().getAnnotation(NoCache.class)!=null){ } } System.out.println((System.currentTimeMillis()-start)+"msec"); System.out.println(Runtime.getRuntime().freeMemory());
結果
以下のようになりました。
4msec
13829000
8msec
13661280
3674msec
13468800
結果は
- マーカーインターフェース(instanceof)
- マーカーインターフェース(isAssignableFrom)
- アノテーション
の順で、処理速度が速く使用メモリが少ないという事になりました。
なので、マーカーインターフェースで実装してinstanceofで確認することにします。
ただ、1億回もループしてこの程度ですけどね。