アセットのデータ取得方法によるパフォーマンス測定(その1)

今、世界はクリスマスムードにつつまれています。クリスマスツリー、クリスマスケーキ、クリスマスプレゼント、クリスマスソング、クリスマスパーティ、クリスマスイベント、クリスマスセールなどなどクリスマスがつくものが楽しさあふれでていますね。

そこで今回は、アセット(フレックスファミリーアセット)のデータを取得するのに、より速い取得の方法はないか調べて、皆様にお届けしたいと思います。christomas_1

たくさんのアセットを参照しているページは、キャッシュがきれている状態でページへアクセスすると、少し重く感じられますよね。少しでも早くページが表示されるように、パフォーマンスを考慮した実装が必須になります。今回は、フレックスアセットのデータの取り方に絞って探ってみようと思います。

今回は、WCSで用意されているタグを使って調べてみます。

データの取得にはassetset:getattributevaluesタグと、assetset:getmultiplevaluesタグが用意されています。この2つのタグの処理時間に違いはあるのでしょうか。2つのタグを使って処理時間を計測し、どちらのタグが速い処理を行っているか測ってみます。

アセット1コのデータを取得しただけでは、わからないので、アセット10コ、50コ、100コで計測してみましょう。

データの取得は、アセットがもつ属性から適当に5つ(string型4つ、asset型1つ)を選んでみます。

では、テスト用のテンプレートをそれぞれ作ります。

1)assetset:getattributevaluesタグ


%><assetset:setasset name="asFlexData" type="TestAsset_C" id='<%= ics.GetVar("aidAssetId") %>' /><%

%><assetset:getattributevalues name="asFlexData" attribute="testA" listvarname="listFlexData" typename="TestAsset_A" /><%
%><ics:if condition='<%= ics.GetList("listFlexData")!=null && ics.GetList("listFlexData").hasData() %>'><ics:then><%
  %><ics:listget listname="listFlexData" fieldname="value" output="o_testA" /><%
%></ics:then></ics:if><%
%><assetset:getattributevalues name="asFlexData" attribute="testB" listvarname="listFlexData" typename="TestAsset_A" /><%
%><ics:if condition='<%= ics.GetList("listFlexData")!=null && ics.GetList("listFlexData").hasData() %>'><ics:then><%
  %><ics:listget listname="listFlexData" fieldname="value" output="o_testB" /><%
%></ics:then></ics:if><%
%><assetset:getattributevalues name="asFlexData" attribute="testC" listvarname="listFlexData" typename="TestAsset_A" /><%
%><ics:if condition='<%= ics.GetList("listFlexData")!=null && ics.GetList("listFlexData").hasData() %>'><ics:then><%
  %><ics:listget listname="listFlexData" fieldname="value" output="o_testC" /><%
%></ics:then></ics:if><%
%><assetset:getattributevalues name="asFlexData" attribute="testD" listvarname="listFlexData" typename="TestAsset_A" /><%
%><ics:if condition='<%= ics.GetList("listFlexData")!=null && ics.GetList("listFlexData").hasData() %>'><ics:then><%
  %><ics:listget listname="listFlexData" fieldname="value" output="o_testD" /><%
%></ics:then></ics:if><%
%><assetset:getattributevalues name="asFlexData" attribute="testE" listvarname="listFlexData" typename="TestAsset_A" /><%
%><ics:if condition='<%= ics.GetList("listFlexData")!=null && ics.GetList("listFlexData").hasData() %>'><ics:then><%
  %><ics:listget listname="listFlexData" fieldname="value" output="o_testE" /><%
%></ics:then></ics:if><%

2)assetset:getmultiplevaluesタグ

%><assetset:setasset name="asFlexData" type="TestAsset_C" id='<%= ics.GetVar("aidAssetId") %>' /><%

%><assetset:getmultiplevalues name="asFlexData" byasset="false" immediateonly="true" prefix="atlst"><%
  %><assetset:sortlistentry attributetypename="TestAsset_A" attributename="testA"/><%
  %><assetset:sortlistentry attributetypename="TestAsset_A" attributename="testB"/><%
  %><assetset:sortlistentry attributetypename="TestAsset_A" attributename="testC"/><%
  %><assetset:sortlistentry attributetypename="TestAsset_A" attributename="testD"/><%
  %><assetset:sortlistentry attributetypename="TestAsset_A" attributename="testE"/><%
%></assetset:getmultiplevalues><%

%><ics:if condition='<%= ics.GetList("atlst:testA")!=null && ics.GetList("atlst:testA").hasData() %>'><ics:then><%
  %><ics:listget listname="atlst:testA" fieldname="value" output="o_testA" /><%
%></ics:then></ics:if><%
%><ics:if condition='<%= ics.GetList("atlst:testB")!=null && ics.GetList("atlst:testB").hasData() %>'><ics:then><%
  %><ics:listget listname="atlst:testB" fieldname="value" output="o_testB" /><%
%></ics:then></ics:if><%
%><ics:if condition='<%= ics.GetList("atlst:testC")!=null && ics.GetList("atlst:testC").hasData() %>'><ics:then><%
  %><ics:listget listname="atlst:testC" fieldname="value" output="o_testC" /><%
%></ics:then></ics:if><%
%><ics:if condition='<%= ics.GetList("atlst:testD")!=null && ics.GetList("atlst:testD").hasData() %>'><ics:then><%
  %><ics:listget listname="atlst:testD" fieldname="value" output="o_testD" /><%
%></ics:then></ics:if><%
%><ics:if condition='<%= ics.GetList("atlst:testE")!=null && ics.GetList("atlst:testE").hasData() %>'><ics:then><%
  %><ics:listget listname="atlst:testE" fieldname="value" output="o_testE" /><%
%></ics:then></ics:if><%

※アセットを格納したリスト作成、ループ処理のコードは省略しています。

測定開始です。

・・・測定・・・測定・・・測定・・・。

出ました。結果です。

アセット数

属性数

タグ

assetset:getattributevalues

assetset:getmultiplevalues

10

5

50.8ms

43.4ms

50

5

438.2ms

256ms

100

5

922.2ms

514.4ms

※動作環境や定義がもつ属性の数によって変動はあります。正確な数値ではありません。

※同じアセットタイプ、同じ定義で、すべて異なるアセットを使っています。

※フレックスアセットの参照はassetset:setassetタグを使っています。

結果を見てみましょう。assetset:getmultiplevaluesタグが速いですね。

assetset:getattributevaluesタグは、アセット数と処理時間を見ると、単純に倍の時間がかかるというわけではなさそうですね。アセット数が多ければ多いほど、時間がかかります。アセットや条件を変更して測っても同じような結果がでました。ということで、アセットタグは、assetset:getmultiplevaluesを使うで決まりですね!メリークリスマスです!

ただ、assetset:getmultiplevaluesタグのデメリットはtext型の属性は取得できないという点です。これは仕様です。ですので、text型の属性は、assetset:getattributevaluesタグを使って取得するしかないですね。うまく使い分けをすれば、十分なパフォーマンスを得ることができると思います。

では、assetAPIを使うとどうでしょうか。タグより速いのでしょうか。

次回(3月頃を予定)はassetAPIを使って測定してみようと思います。christomas_2


【新機能】Vanity URLを試してみる(その1)

今回は、WebCenter Sites 11g (以下WCSと記述)の最新バージョン 11.1.1.8.0 (2013年12月09日時点)から実装された新機能のVanity URLを試してみたいと思います。

1. Vanity URLとは?

まず、Vanity URLとは何か?

Vanity という単語を翻訳してみますと、「虚栄」とか「虚飾」と出てきます。さらに国語辞典で「虚栄」を調べてみると「実質の伴わないうわべだけの栄誉」と出てきました。要するに中身のない見せかけのURLということになります。

WCSのVanity URLとは、ある実際のURLを別の見せかけのURLに変更できる機能となります。通常、WCSで生成されるURLはクエリ文字列を複数組み合わせたものになりますが、それを別の任意のURLに見せかけることができます。その結果、直感的に分かりやすく、また、SEOで優位となるURLを用いることが出来ます。

WCSにはURLアセンブラという同等の機能があります。(11.1.1.8.0でも使えます)その機能との違いについてもおいおい考えてみます。

※以降の検証はJumpstart Kit(以下JSKと記述)の11.1.1.8.0版 のサンプルサイト FirstSiteII を用いて行いました。JSKのインストール方法や使い方については割愛いたします。

※ドキュメントは特に明記しない限りWCSのAdministrator’s Guideを参照しました。

http://docs.oracle.com/cd/E29542_01/doc.1111/e29636/config_vanity_url.htm

2. WebRoots の設定

ドキュメントによると WebRoot は異なった環境でVanity URLがどのように解釈されるかを制御するものとあります。WCSの開発では通常、開発環境、編集環境、配信環境と3つに分かれているケースが多いため、それぞれの環境に対応するためのものかもしれませんが、今回は検証はJSKで行うためあまり気にせず、最初からサンプルとして登録されているものを使用します。

WebRoots_settinig1

Admin UI にログインし、「管理」タブの「WebRoots」以下にFSIIが存在しています。

今回はこれをそのまま使うことにします。

ルートURLにhttp://localhost:9080/cs/fsii が設定されています。

3. Vanity URLの設定

Vanity URLは二つの設定方法により構築することができます。

  • アセットごとの手動設定
  • アセットタイプごとの自動設定(blobも含む)

手動設定では一つ一つのアセットに対して手動でURLを設定します。よってそのアセットを用いて表示しているページのURLを一つ一つ手動で設定する必要があります。

自動設定の場合はアセットのタイプ毎に(もしくは定義ごと)に自動でURLを設定するものとなります。同じアセットタイプのアセットを用いて表示しているページは一つ一つ設定しなくても同じURLパターンとすることができます。この場合は、URLの一部にアセットを識別するための情報を持つ必要があります。

今回はアセットの手動設定方法を試してみます。(自動設定は次回)

4. アセットごとの手動設定

(参考:User’s Guide:http://docs.oracle.com/cd/E29542_01/doc.1111/e29605/user_formmode_createdit.htm#BABJCGIJ

JSKを起動しFirstSite IIのホームを表示すると以下のようなURLとなっています。

manual_setting_0

http://localhost:9080/cs/Satellite?c=Page&childpagename=FirstSiteII%2FFSIILayout&cid=1118867611403&pagename=FSIIWrapper&rendermode=previewnoinsite

クエリを複数組み合わせたURLとなり、長くて分かりづらいです。

今回はこのURLをVanity URLに変更してみます。

今回はアセット毎のVanity URLの設定ということで、アセットにURLを設定するのですが、その際ページの表示に用いるプライマリアセットに設定する必要があります。

先のURLを見ると分かる通りc=Page、cid=1118867611403 となっているため、アセットタイプがPageでidが1118867611403であるものがプライマリアセットとなります。Contributor UI を起動し、サイトツリーから該当のアセットを参照します。

manual_setting_2

URLタブをクリックし、鉛筆アイコンをクリックします。

manual_setting_3

URL 見せかけのURLを設定します。今回は 「home.html 」とします。
ホスト WebRoots で設定した値が入力されているため、そのままとします。※ホストとURLに設定した文字列を組み合わせたURL

http://localhost:9080/cs/fsii/home.html

が実際にアクセスされるVanity URLとなります。

デバイスグループ 今回はこのままとします。
Template 「FSIILayout」を設定します。ホーム現行のURLのchildpagenameに設定されているものとなります。
ラッパー 「FSIIWrapper」とします。ホーム現行のURLのpagenameに設定されているものとなります。

その後、「追加」ボタンをクリックします。

調査画面に戻りURLが追加されていることを確認します。

manual_setting_4

では、このURLでアクセスできることを試してみます。

manual_setting_5

無事にアクセスできました。

また、HTML中のHomeへのリンクもVanity URLに変更されていることを確認します。

manual_setting_6

以上でアセット毎のVaniy URL の手動設定は完了です。非常に簡単です。

次に設定周りを確認しておきます。

5.Vanity URLを使う際の設定

今回のJSKのサンプルサイトの場合はすでに設定されているため特に改めて設定を行う必要はありませんが、Vanity URL自体を使うには、URLリファレンスフィルターの設定が必要となり、また、直接Vanity URLに設定したURLでアクセスできるためには、URLリライトフィルターの設定が必要となります。

まずURLリライトフィルターから見ていきます。

  • URLリライトフィルター

アプリケーションのweb.xmlを参照します。

<filter>
<filter-name>URLRewriteFilter</filter-name>
<filter-class>COM.FutureTense.Servlet.URLRewriteFilter</filter-class>
<init-param>
<param-name>SitePrefix</param-name>
<param-value>fsii,avi</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>URLRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

上記の設定ではコンテキストパス /cs にサイトプレフィックスを加えたパス以下すべてに対してURLリライトが有効となります。

/cs/fsii/*

よって、今回設定した、/cs/fsii/home.html はURLリファレンスフィルターで処理されます。

URLリライトフィルターでは内部的にURLを以下の形式に分割します。

http://localhost:9080/cs/Sites?lookuppage=/cs/fsii/home.html&lookuphost=http://localhost

ここでSites というサーブレットが出来ますが、こちらはURLリファレンスフィルターによって処理されます。

  • URLリファレンスフィルター

こちらもデフォルトで設定がされています。(基本変更する必要はないと思います)

<filter>
<filter-name>WebReferenceFilter</filter-name>
<filter-class>COM.FutureTense.Servlet.WebReferenceFilter</filter-class>
</filter>
<filter-name>WebReferenceFilter</filter-name>
<url-pattern>/Sites/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>

Vanity URLはこちらのフィルターによってメインで処理が行われます。

lookuppageとlookuphost のパラメータで渡ってきた値に対応するVanity URLの設定があれば、そのURLに対応するページが表示されます。

このlookuppageとlookpuhost をクエリとして渡すことができるのであれば、administrator’s guide にあるように、Apacheのmod_rewrite でアクセスしても構いません。その場合はURLリライトフィルターを用いずに対応が可能となります。

6.まとめ

簡単にまとめますと、手動設定ではプライマリアセット一つ一つに対して任意のURLを設定できます。その見せかけのURLにアクセスされた場合、URLからプライマリアセットが特定され、同時に設定したテンプレート等の情報からURLが生成され、ページが表示されます。(おそらく内部的にそうなっているのだろうと思います)

また、Vanity URLを設定したURLでアクセスできるページへのリンクが設定されている箇所についても同時にVanity URLに置き換えられます。

設定はURLリファレンスフィルターが必要となり、必要に応じてURLリライトフィルターを用います。

URLアセンブラでも同等のことは実装次第では行うことが可能かも知れません。ただ、URLアセンブラではURLの変換ロジック部分を自分で実装する必要があり、またContributor との連携もおそらくありません。詳細は次回にもう少し考えてみます。

  • 次回予告(3月頃予定)

Vanity URLの自動設定を試してみます。

First SiteII の On Sale Items のリスト内の各詳細ページへのリンクURLは現在URLアセンブラにてURLが設定されています。

例えば、一番上の「Nanomax Flat-Panel LCD HDTV」のURLは以下の通りとなっています。

http://localhost:9080/cs/Satellite/FirstSiteII/FSII/Product_C/1196193243217/1118867611403?packedargs=locale%3D1154551493541

こちらの上書きという形でVanity URLの自動設定を設定してみます。

manual_setting_0

※上記の記述は担当が調査した範囲での記述となります。その正確性、完全性についてはジークス社は責任を負いません。