読者です 読者をやめる 読者になる 読者になる

なんとなく

誰得感満載な記事が多いかも。Mono関係とLinuxのサーバ関係、レビューとか。

さくらのVPSでOSgridのパフォーマンス監視設定

OpenSim

今回は、さくらのVPSおよびOSgridのパフォーマンスの視覚化について触れていきたいと思います。

内容

  • はじめに
  • Stats(統計情報)
    • さくらのVPSのStats(統計情報)
    • OpenSimのStats(統計情報)
  • 視覚的にしてみる
    • システム側およびOpensimから出力されるXMLの統計情報の蓄積について(collectd)
    • 統計情報のrrdtoolで描画について

はじめに

さくらのVPS512MBを借りていて、OSgridに接続する自分が運用するOpesSimサーバ*1に複数アバターを作成して、テストで入ってみるとなんだか重いことが多かったので、実際のところどのような状況になっているのだろうかと思い、データを取得しグラフ化してみました。

パフォーマンスを監視することはサーバの管理にとって適切なリソースなのかを把握するのに重要です。そして、数値データだけではなかなか把握しにくいので、グラフにして視覚化し把握することも重要です。

さくらのVPSはOpenSimのテストのみの目的で借りているので、システム側のリソース監視とOpenSim側のリソース監視をすることによってほぼ、OpenSimのシステムとしてのパフォーマンスを知ることができます。
では、システムとOpenSimのリソース監視(統計情報)について見ていきたいと思います。

Stats(統計情報)

さくらのVPSのStats(統計情報)

ほぼOpensimの運用しか使用していないので、CPU、メモリ、ネットワークの状況についてはOpensimで使用するものとみなすことができるので、Opensimのstatsと一緒に統計情報を取得します。CentOSでは、sysstatを使用すれば、ログを取得できますし、さくらのVPSではデフォルトでインストールされています。

OpenSimのStats(統計情報)
OpenSimより出力される統計情報

以下に示すものがOpenSimより統計情報として出力されます。私なりの説明を加えるので、間違えていたら指摘していただきたいです。

説明
AgentCount SIMにいるユーザー(Avatar)の数
ChildAgentCount SIMにはいないがこのSIMのオブジェクト?を表示しているユーザー(Avatar)の数
GCMemory OpenSim.exeが動的に確保したメモリ領域のうち、不要になった領域を自動的に解放した量
ObjectCount SIMのオブジェクトの数
PhysicsFrame 物理的エンジンが実行されているフレーム数
PhysicsUpdateFrame 物理的エンジンで更新のあったフレーム数(たぶん)
PWSMemory OpenSim.exeの実行プロセスのメモリ使用量(ソースを見るとSystem.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64;で取得している)
ThreadCount OpenSim.exeのスレッド数
TotalFrame 総フレーム数(たぶん)詳しくは、OpenSim/Region/Framework/Scenes/Scene.csを見たほうがいい
EventFrame イベントフレーム数(たぶん)詳しくは、OpenSim/Region/Framework/Scenes/Scene.csを見たほうがいい
LandFrame 土地のフレーム数(たぶん)詳しくは、OpenSim/Region/Framework/Scenes/Scene.csを見たほうがいい
LastFrameTime 完了フレーム数(たぶん)詳しくは、OpenSim/Region/Framework/Scenes/Scene.csを見たほうがいい
TimeDilation 実時間に対する物理的シミュレーションレート。 1.0 はフルスピードで地域が実行されていることを示し、0.5 はその半分のスピードで物理的作用が実行されていることを示す
SimFPS SIMのFPS
PhysicsFPS SIMの物理的エンジンが実行されているFPS
AgentUpdatesPerSecond SIMのユーザー(Avatar)が更新される率。 通常は 1 秒あたり 20 回の更新で、地域に多くのエージェントがいる場合、この値は低下するらしい
ObjectUpdatesPerSecond SIMのオブジェクトが更新される率。 通常は 1 秒あたり 20 回の更新で、地域に多くのエージェントがいる場合、この値は低下するらしい
ActiveObjectCount SIMにおける移動中または変更中のオブジェクトの数
ActiveScripts ユーザー(Avatar)が装着しているスクリプトを含む、SIMで現在実行されているスクリプトの数
ScriptEventsPerSecond SIMで 1 秒間に実行されている LSL オペレーション コードの数
InPacketsPerSecond SIMで 受信されたUDP パケット
OutPacketsPerSecond SIMで 送信されたUDP パケット
UnackedBytes unacked(応答確認なしデータのバイト数)
PendingDownloads 保留中のSIMからのAssetダウンロード数。 これが 1 よりも大きい値の場合、これはノートカードやスクリプトの閲覧、オブジェクトの rez において遅延が生じる可能性があることを意味するらしい
PendingUploads 保留中のSIMへのAssetデータの現在のアップロード数です。 この数値がゼロ以外だと、テレポート実行の際、パフォーマンスに問題が起こる可能性があるらしい
TotalFrameTime SIMでフレームごとに実行している操作の完了までにかかる時間
NetFrameTime ネットワーク データの受信に対してかかった時間
PhysicsFrameTime 物理的作用のシミュレーション実行にフレームが費やした時間。 通常は 5 ミリ秒未満らしい
SimulationFrameTime その他のシミュレーション実行にフレームが費やした時間 (エージェントの動き、天候のシミュレーションなど)
AgentFrameTime エージェント(Avatar)へのオブジェクト データの更新および送信にかかった時間
ImagesFrameTime イメージ データの更新およびエージェント(Avatar)への転送にかかった時間
Webでの統計情報の出力

OpenSimの統計情報は、ブラウザでも確認できるようです。
http://opensimulator.org/wiki/Web_Statistics_Moduleによると、OpenSim.ini において

[WebStats]
enabled=true

とし(ない場合は追加します)、ブラウザで以下のようにURIを入力することで

http://サーバのIPアドレス:9000/SStats/

統計情報を見ることができます。ただし、認証をかけることができないようなので、誰からも見ることが出来る環境では、reloadを数多く短時間にすることなどで高負荷を発生しすることができるという可能性があるため、falseにしておいたほうが良いと思われます。(OSgridのデフォルトだとenabled=trueなのですが、何か意図があって使用しているのかもしれません?要調査です。)*2

XMLによる統計情報の出力

OpenSimの統計情報は、XMLの出力も可能なようです。JSONはないんだろうかという疑問は浮かびますが*3

http://opensimulator.org/wiki/Monitoring_Moduleによると、OpenSim.ini においてデフォルトでXMLの出力は有効になっているので、使用したくない場合は、明示的にfalseにしてあげる必要があるようです。今回は、このXMLによる統計情報の出力を使ってデータを収集するので、falseにすることはありません。

XMLでの出力は以下のようにして確認することができます。

http://サーバのIPアドレス:9000/monitorstats/UUID

当方の環境はメガリージョンですが、monitorstatsの仕様は、複数SIMがありポートをそれぞれ割り当てていますが、1SIMのように認識するため、各SIMに割当たっているポートではなく9000のみを使用し、UUIDを変えればいいようです。
ブラウザを用いて確認すると以下のように出力されます。

<data>
<AgentCountMonitor>0</AgentCountMonitor>
<ChildAgentCountMonitor>0</ChildAgentCountMonitor>
<GCMemoryMonitor>511221760</GCMemoryMonitor>
<ObjectCountMonitor>12585</ObjectCountMonitor>
<PhysicsFrameMonitor>0</PhysicsFrameMonitor>
<PhysicsUpdateFrameMonitor>0</PhysicsUpdateFrameMonitor>
<PWSMemoryMonitor>2796699648</PWSMemoryMonitor>
<ThreadCountMonitor>0</ThreadCountMonitor>
<TotalFrameMonitor>0</TotalFrameMonitor>
<EventFrameMonitor>0</EventFrameMonitor>
<LandFrameMonitor>0</LandFrameMonitor>
<LastFrameTimeMonitor>63</LastFrameTimeMonitor>
<TimeDilationMonitor>1</TimeDilationMonitor>
<SimFPSMonitor>55.3333320617676</SimFPSMonitor>
<PhysicsFPSMonitor>56.6666679382324</PhysicsFPSMonitor>
<AgentUpdatesPerSecondMonitor>0</AgentUpdatesPerSecondMonitor>
<ObjectUpdatesPerSecondMonitor>0</ObjectUpdatesPerSecondMonitor>
<ActiveObjectCountMonitor>0</ActiveObjectCountMonitor>
<ActiveScriptsMonitor>760</ActiveScriptsMonitor>
<ScriptEventsPerSecondMonitor>0</ScriptEventsPerSecondMonitor>
<InPacketsPerSecondMonitor>1</InPacketsPerSecondMonitor>
<OutPacketsPerSecondMonitor>1.33333337306976</OutPacketsPerSecondMonitor>
<UnackedBytesMonitor>0</UnackedBytesMonitor>
<PendingDownloadsMonitor>0</PendingDownloadsMonitor>
<PendingUploadsMonitor>0</PendingUploadsMonitor>
<TotalFrameTimeMonitor>4</TotalFrameTimeMonitor>
<NetFrameTimeMonitor>0</NetFrameTimeMonitor>
<PhysicsFrameTimeMonitor>4</PhysicsFrameTimeMonitor>
<SimulationFrameTimeMonitor>0</SimulationFrameTimeMonitor>
<AgentFrameTimeMonitor>0</AgentFrameTimeMonitor>
<ImagesFrameTimeMonitor>0</ImagesFrameTimeMonitor>
</data>

このXMLを定期的に取得し、視覚化することで今回の目的が達成されます。
では、次に実際に視覚化する手順を見ていきます。

視覚的にしてみる

1時間毎、日毎、週ごとなど、取得したデータを視覚化し、トレンド把握し、分析することで、どの程度のパフォーマンスなのかを把握することができます。

視覚化の要件として、以下を設定しました。

  1. システム側およびOpensimから出力されるXMLの統計情報を一つのツールで蓄積できる
  2. 一つのツールでグラフ化することができる
  3. 制限付きの公開をする

調べるとcollectd*4というツールを使用すれば、1.が実現でき、1.でのデータをrrdtool*5というツールを使用することで、2.が実現できるようでした。そしてApacheを使えば、3.が実現できることがわかりました。
その他にも実現できるものを調べていたら、リッチなサーバサイドのアプリケーションによる実現もあったのですが、リッチなUIはいりませんし、ある程度データが確認出来ればいいし、サーバに余計な負荷を掛けたくないので、collectdで蓄積したrrdtool形式のデータをshellでrrdtoolを実行することでグラフ化しています。その方法を以下に示します。

システム側およびOpensimから出力されるXMLの統計情報の蓄積について(collectd)
collectdのインストール
[root@foo ~]# yum install collectd

collectdのインストールと同時にグラフ化するツールであるrrdtoolのインストールも同時にしておきます。

[root@foo ~]# yum install rrdtool

collectdからrrdtoolで描画できるデータを出力するためのプラグインをインストールします。

[root@foo ~]# yum install collectd-rrdtool
collectdの起動の確認

デフォルトのcollectdの設定では、CPUとメモリとネットワークインターフェイスについて取得しているので、確認のために起動し、rrd形式での出力がされているか確認します。

[root@foo ~]# /etc/init.d/collectd start

データが出力されているか確認します。collectdから出力されるデータはデフォルトでは/var/lib/collectd/にサーバのFQDNのディレクトリ以下に作成されるようです。

[root@foo ~]# ls -la /var/lib/collectd/サーバのFQDN/

CPUやmemoryのディレクトリができているか確認します。
タイムスタンプが起動した時刻であり、ディレクトリの中にファイルができていることを確認します。

[root@foo ~]# ls -la /var/lib/collectd/サーバのFQDN/memory/
collectdの設定

collectdでデータを取得するためには、以下2点を行う必要があります。

  • こういう形式でデータを取るからねという定義を指定する
  • どこからどういうデータを取得するという設定をする

http://opensimulator.org/wiki/Collectdにおいて、どのような定義をすればいいのか、どこからどういうデータを取得する設定をすることについて記述してあるので、参考にして進めていきます。

まず、CentOSの場合、取得するデータを保存する際のデフォルトの定義が

/usr/share/collectd/types.db

にあるので、OpenSimで出力されるデータを追加し、定義します。

[root@foo ~]# vi /usr/share/collectd/types.db
Dvgtu_agent_count       value:GAUGE:0:U
Dvgtu_child_agent_count value:GAUGE:0:U
Dvgtu_gc_memory value:GAUGE:0:U
Dvgtu_object_count      value:GAUGE:0:U
Dvgtu_physics_frame     value:GAUGE:0:U
Dvgtu_physics_update    value:GAUGE:0:U
Dvgtu_pws_memory        value:GAUGE:0:U
Dvgtu_thread_count      value:GAUGE:0:U
Dvgtu_total_frame       value:GAUGE:0:U
Dvgtu_event_frame       value:GAUGE:0:U
Dvgtu_land_frame        value:GAUGE:0:U
Dvgtu_last_frame        value:GAUGE:0:U
Dvgtu_time_dilatation   value:GAUGE:0:U
Dvgtu_sim_fps   value:GAUGE:0:U
Dvgtu_physics_fps       value:GAUGE:0:U
Dvgtu_agent_updates_per_sercond value:GAUGE:0:U
Dvgtu_object_updates_per_second value:GAUGE:0:U
Dvgtu_active_object_count       value:GAUGE:0:U
Dvgtu_active_scripts    value:GAUGE:0:U
Dvgtu_script_events_per_second  value:GAUGE:0:U
Dvgtu_in_paquets_per_second     value:GAUGE:0:U
Dvgtu_out_paquets_per_second    value:GAUGE:0:U
Dvgtu_unacked_bytes     value:GAUGE:0:U
Dvgtu_pending_downloads value:GAUGE:0:U
Dvgtu_pending_uploads   value:GAUGE:0:U
Dvgtu_total_frame_time  value:GAUGE:0:U
Dvgtu_net_frame_time    value:GAUGE:0:U
Dvgtu_physics_frame_time        value:GAUGE:0:U
Dvgtu_simulation_frame_time     value:GAUGE:0:U
Dvgtu_agent_frame_time  value:GAUGE:0:U
Dvgtu_images_frame_time value:GAUGE:0:U

Dvgtu_agent_countなどは定義名ですので、任意につけることができます。ただし、以下に記述する/etc/collectd.conf内のLoadPlugin curl_xmlにおけるType "Dvgtu_agent_count"と合わせる必要があります。
そして、/etc/collectd.confにおいて、定義した名前にXMLで出力されるURIからどういう形式で取得したデータをローカルに保存するかを指定する必要があります。URIは以下のように記述します。

http://サーバのIPアドレス:9000/monitorstats/各SIMに割当たっているUUID

当方の環境はメガリージョンなので、ブラウザを用いて各SIMにおいてXMLが出力されるか、Regions.iniに記述してあるUUIDを各々入力して、確認します。
XMLが出力されることが確認できたら、/etc/collectd.confに設定を追加します。

[root@foo ~]# vi /etc/collectd.conf
LoadPlugin curl_xml
<Plugin "curl_xml">
<URL "http://サーバのIPアドレス:9000/monitorstats/UUID">
    Instance "Dvgtu0"
    <XPath "/data">
      Type "Dvgtu_agent_count"
      ValuesFrom "AgentCountMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_child_agent_count"
      ValuesFrom "ChildAgentCountMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_gc_memory"
      ValuesFrom "GCMemoryMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_object_count"
      ValuesFrom "ObjectCountMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_physics_frame"
      ValuesFrom "PhysicsFrameMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_physics_update"
      ValuesFrom "PhysicsUpdateFrameMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_pws_memory"
      ValuesFrom "PWSMemoryMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_thread_count"
      ValuesFrom "ThreadCountMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_total_frame"
      ValuesFrom "TotalFrameMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_event_frame"
      ValuesFrom "EventFrameMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_land_frame"
      ValuesFrom "LandFrameMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_last_frame"
      ValuesFrom "LastFrameTimeMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_time_dilatation"
      ValuesFrom "TimeDilationMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_sim_fps"
      ValuesFrom "SimFPSMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_physics_fps"
      ValuesFrom "PhysicsFPSMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_agent_updates_per_sercond"
      ValuesFrom "AgentUpdatesPerSecondMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_object_updates_per_second"
      ValuesFrom "ObjectUpdatesPerSecondMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_active_object_count"
      ValuesFrom "ActiveObjectCountMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_active_scripts"
      ValuesFrom "ActiveScriptsMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_script_events_per_second"
      ValuesFrom "ScriptEventsPerSecondMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_in_paquets_per_second"
      ValuesFrom "InPacketsPerSecondMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_out_paquets_per_second"
      ValuesFrom "OutPacketsPerSecondMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_unacked_bytes"
      ValuesFrom "UnackedBytesMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_pending_downloads"
      ValuesFrom "PendingDownloadsMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_pending_uploads"
      ValuesFrom "PendingUploadsMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_total_frame_time"
      ValuesFrom "TotalFrameTimeMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_net_frame_time"
      ValuesFrom "NetFrameTimeMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_physics_frame_time"
      ValuesFrom "PhysicsFrameTimeMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_simulation_frame_time"
      ValuesFrom "SimulationFrameTimeMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_agent_frame_time"
      ValuesFrom "AgentFrameTimeMonitor/text()"
    </XPath>
    <XPath "/data">
      Type "Dvgtu_images_frame_time"
      ValuesFrom "ImagesFrameTimeMonitor/text()"
    </XPath>
  </URL>
同様に、URLを変更、Instatnceを被らないようにして繰り返し
</Plugin>

他にあと2点、/etc/collectd.confを修正します。
インターバルがデフォルトだと10秒ごとなので、20秒ごとにします。問い合わせの回数が多くなることでOpenSim.exeを高負荷にしてしまうのではないかということに対する考慮です。また、Swapのプラグインが有効になっていないので、コメントアウトを外して、有効にしてあげます。

[root@foo ~]# vi /etc/collectd.conf
Interval     20
LoadPlugin swap

collectdを再起動します。

[root@foo ~]# /etc/init.d/collectd restart

20秒ごとにデータを蓄積してくれるようになります。

ここで、システムとOpenSimの統計情報を取得するためのcollectdの設定が完了したので、初期起動の設定をしておきます。Run Level 3になっているかの確認です。

[root@foo ~]# chkconfig --list collectd
[root@foo ~]# chkconfig collectd on
[root@foo ~]# chkconfig --list collectd

統計情報のrrdtoolで描画について

では、collectdを使用することによって蓄積されたデータをグラフ化にするためのrrdtoolの簡単な使い方について触れていきたいと思います。詳しいrrdtoolの使用方法については、検索していただければと思います。

rrdtoolで描画する方法の例

memoryの使用率を描画する方法を一例としてあげます。

collectdのインストールと一緒にrrdtoolもインストールしておいたので、まずはrrdtoolがインストールされていることを確認します。

[takeshich@foo~]$ rrdtool

collectdから出力されるデータは

/var/lib/collectd/サーバのFQDN/

にInstanceごとにディレクトリ作成されその下にrrdファイルが作成されます。

PNGで320x100のグラフを現在より30分前からの30分間をプロットする例です

[takeshich@foo ~]$ RRDDATAFILE=/var/lib/collectd/サーバのFQDN/memory/
[takeshich@foo ~]$ rrdtool graph --imgformat PNG test.png \
     --start -30minutes  --width 320 --height 100 \
     -n DEFAULT:0:"Bitstream Vera Sans" \
     --vertical-label "Memory_Used(Byte)" \
     --title "Memory_Used" \
     DEF:used_avg=${RRDDATAFILE}memory-used.rrd:value:AVERAGE \
     DEF:used_min=${RRDDATAFILE}memory-used.rrd:value:MIN \
     DEF:used_max=${RRDDATAFILE}memory-used.rrd:value:MAX \
     CDEF:used_nnl=used_avg,UN,0,used_avg,IF \
     AREA:used_nnl#bfbfff \
     LINE1:used_nnl#0000ff:used      \
     GPRINT:used_avg:AVERAGE:"avg\:%4.2lf%s"   \
     GPRINT:used_min:MIN:"min\:%4.2lf%s"       \
     GPRINT:used_max:MAX:"max\:%4.2lf%s"      \
     GPRINT:used_avg:LAST:"cur\:%4.2lf%s\n"

こんな感じで出力されます。

OpenSimの出力データも同様にして描画できますので、GCMemoryの値を描画してみます。
以下パスに/etc/collectd.confで設定したプラグインと指定したinstance名でディレクトリが作られそこにデータが格納されるので、上記と同様に描画してみます。

/var/lib/collectd/サーバのFQDN/curl_xml-Dvgtu0
[takeshich@foo~]$ RRDDATAFILE=/var/lib/collectd/サーバのFQDN/curl_xml-Dvgtu0/
[takeshich@foo ~]$ rrdtool graph --imgformat PNG gc.png \
     --start -30minutes  --width 320 --height 100 \
     -n DEFAULT:0:"Bitstream Vera Sans" \
     --vertical-label "ガベコレ(Byte)" \
     --title "ガベコレ" \
     DEF:used_avg=${RRDDATAFILE}Dvgtu_gc_memory.rrd:value:AVERAGE \
     DEF:used_min=${RRDDATAFILE}Dvgtu_gc_memory.rrd:value:MIN \
     DEF:used_max=${RRDDATAFILE}Dvgtu_gc_memory.rrd:value:MAX \
     CDEF:used_nnl=used_avg,UN,0,used_avg,IF \
     AREA:used_nnl#bfbfff \
     LINE1:used_nnl#0000ff:used      \
     GPRINT:used_avg:AVERAGE:"avg\:%4.2lf%s"   \
     GPRINT:used_min:MIN:"min\:%4.2lf%s"       \
     GPRINT:used_max:MAX:"max\:%4.2lf%s"      \
     GPRINT:used_avg:LAST:"cur\:%4.2lf%s\n"

rrdtoolで描画(シェル)

上記のようにすれば描画できることが確認できたので、以下仕様でシェルを作成することにしました。

  • 描画対象
    • システム
      • CPU使用率
      • Memoryの使用量とSwapの量
      • ネットワークインターフェイスのINとOUTの量
    • OpenSim(取得できるデータすべて)
  • 描画する期間
    • 30分ごと
    • 60分ごと
    • 1日ごと
    • 1週間ごと
  • 描画タイミング
    • 10分毎(期間が30分,60分)
    • 1時間ごと(期間が1日,1週間)
  • 描画サイズ(640x100)

OpenSimのデータは数が多いので、生成されたデータの一覧をそのまま描画する形になっています。メガリージョンの環境なので、積算してグラフ化したほうがいいものもあるようです。追って対応していきたいと考えています。

[root@foo ~]# vi /home/takeshich/rrdgraph.sh
#!/bin/bash
#-----------------------------------------------------------
#collectdで取得したデータをrrdtoolで描画するスクリプト
#-----------------------------------------------------------
#
#・描画対象
# ・システム
#  ・CPU使用率
#  ・Memoryの使用量とSwapの量
#  ・ネットワークインターフェイスのINとOUTの量
# ・OpenSim(取得できるデータすべて)
#・描画する期間
# ・30分ごと
# ・60分ごと
# ・1日ごと
# ・1週間ごと
#・描画タイミング(crontabで設定)
# ・10分毎(期間が30分,60分)
# ・1時間ごと(期間が1日,1週間)
#・描画サイズ(640x100)

#timezoneをいれないと曜日の表示がおかしいようなので
TZ=Asia/Tokyo

#collectdによりrrd形式のファイルが書き出されるPATH
RRDDATAPATH=/var/lib/collectd/サーバのFQDN/

#出力される画像データを保存するディレクトリ
OUTPUTDATAPATH=/home/opensimstats/

#画像ファイル名
PNGNAME=""

#期間
TERM=""

#-----------------------------------------------------------
#OpenSimのデータを描画する
#-----------------------------------------------------------
opensim_plot()
{
#引数1:期間(0:HalfHourly1:Hourly,2:Daily,3:Weekly)
#引数2:SIMの番号(メガリージョンなので、Regions.iniで設定している番号)

case "$1" in
        "0" )
        TERM=HalfHourly
        START="-31minutes" ;;
        "1" )
        TERM=Hourly
        START="-61minutes" ;;
        "2" )
        TERM=Daily
        START="-25hours" ;;
        "3" )
        TERM=Weekly
        START="-8days" ;;
        "" )
        exit ;;
esac

#OpenSimのデータが出力される場所
RRDDATAFILE=${RRDDATAPATH}curl_xml-Dvgtu$2/

#出力されるデータをリストにし、画像を作成
for LIST in `ls ${RRDDATAFILE}`
do
        LISTNAME=`echo ${LIST} | sed -e "s/\.rrd//"`

        rrdtool graph --imgformat PNG ${OUTPUTDATAPATH}curl_xml-Dvgtu$2/${LISTNAME}_${TERM}.png \
             --start ${START}  --width 640 --height 100 \
             -n DEFAULT:0:"Bitstream Vera Sans" \
             --vertical-label " " \
             --title "$2:${LISTNAME}" \
             DEF:opensim_avg=${RRDDATAFILE}${LIST}:value:AVERAGE \
             DEF:opensim_min=${RRDDATAFILE}${LIST}:value:MIN \
             DEF:opensim_max=${RRDDATAFILE}${LIST}:value:MAX \
             AREA:opensim_avg#bfbfff \
             LINE1:opensim_avg#0000ff:${LISTNAME}      \
             GPRINT:opensim_avg:AVERAGE:"avg\:%6.2lf%s"   \
             GPRINT:opensim_min:MIN:"min\:%6.2lf%s"       \
             GPRINT:opensim_max:MAX:"max\:%6.2lf%s"      \
             GPRINT:opensim_avg:LAST:"cur\:%6.2lf%s\n"
done
}

#-----------------------------------------------------------
#ネットワークインターフェイスのデータを描画する
#-----------------------------------------------------------
interface_plot()
{
#引数1:期間(0:HalfHourly1:Hourly,2:Daily,3:Weekly)
case "$1" in
        "0" )
        TERM=HalfHourly
        START="-31minutes" ;;
        "1" )
        TERM=Hourly
        START="-61minutes" ;;
        "2" )
        TERM=Daily
        START="-25hours" ;;
        "3" )
        TERM=Weekly
        START="-8days" ;;
        "" )
        exit ;;
esac

#画像ファイル名
PNGNAME="interface"

#ネットワークインターフェイスのデータが出力される場所
RRDDATAFILE=${RRDDATAPATH}interface/

#画像を作成
rrdtool graph --imgformat PNG ${OUTPUTDATAPATH}${PNGNAME}_${TERM}.png \
     --start ${START}  --width 640 --height 100 \
     -n DEFAULT:0:"Bitstream Vera Sans" \
     --vertical-label "Bytes" \
     --title "eth0 network traffic_${TERM}" \
     DEF:eth0_rx_avg=${RRDDATAFILE}if_packets-eth0.rrd:rx:AVERAGE \
     DEF:eth0_rx_min=${RRDDATAFILE}if_packets-eth0.rrd:rx:MIN \
     DEF:eth0_rx_max=${RRDDATAFILE}if_packets-eth0.rrd:rx:MAX \
     DEF:eth0_tx_avg=${RRDDATAFILE}if_packets-eth0.rrd:tx:AVERAGE \
     DEF:eth0_tx_min=${RRDDATAFILE}if_packets-eth0.rrd:tx:MIN \
     DEF:eth0_tx_max=${RRDDATAFILE}if_packets-eth0.rrd:tx:MAX \
     AREA:eth0_rx_avg#bfbfff \
     LINE1:eth0_rx_avg#0000ff:rx\(IN\)      \
     GPRINT:eth0_rx_avg:AVERAGE:"avg\:%6.2lf%s"   \
     GPRINT:eth0_rx_min:MIN:"min\:%6.2lf%s"       \
     GPRINT:eth0_rx_max:MAX:"max\:%6.2lf%s"      \
     GPRINT:eth0_rx_avg:LAST:"cur\:%6.2lf%s\n" \
     LINE1:eth0_tx_avg#00e000:tx\(OUT\)      \
     GPRINT:eth0_tx_avg:AVERAGE:"avg\:%6.2lf%s"   \
     GPRINT:eth0_tx_min:MIN:"min\:%6.2lf%s"       \
     GPRINT:eth0_tx_max:MAX:"max\:%6.2lf%s"      \
     GPRINT:eth0_tx_avg:LAST:"cur\:%6.2lf%s\n"
}

#-----------------------------------------------------------
#メモリのデータを描画する
#-----------------------------------------------------------
memory_plot()
{
#引数1:期間(0:HalfHourly1:Hourly,2:Daily,3:Weekly)
case "$1" in
        "0" )
        TERM=HalfHourly
        START="-31minutes" ;;
        "1" )
        TERM=Hourly
        START="-61minutes" ;;
        "2" )
        TERM=Daily
        START="-25hours" ;;
        "3" )
        TERM=Weekly
        START="-8days" ;;
        "" )
        exit ;;
esac

#画像ファイル名
PNGNAME="Memory"

#メモリのデータが出力される場所
RRDDATAFILE=${RRDDATAPATH}memory/
#Swapのデータが出力される場所
RRDDATAFILE_SWAP=${RRDDATAPATH}swap/

#画像を作成
rrdtool graph --imgformat PNG ${OUTPUTDATAPATH}${PNGNAME}_${TERM}.png \
     --start ${START}  --width 640 --height 100 \
     -n DEFAULT:0:"Bitstream Vera Sans" \
     --vertical-label "Memory_Used(Byte)" \
     --title "Memory_Used_${TERM}" \
     DEF:used_avg=${RRDDATAFILE}memory-used.rrd:value:AVERAGE \
     DEF:used_min=${RRDDATAFILE}memory-used.rrd:value:MIN \
     DEF:used_max=${RRDDATAFILE}memory-used.rrd:value:MAX \
     CDEF:used_nnl=used_avg,UN,0,used_avg,IF \
     DEF:sused_avg=${RRDDATAFILE_SWAP}swap-used.rrd:value:AVERAGE \
     DEF:sused_min=${RRDDATAFILE_SWAP}swap-used.rrd:value:MIN \
     DEF:sused_max=${RRDDATAFILE_SWAP}swap-used.rrd:value:MAX \
     CDEF:sused_nnl=sused_avg,UN,0,sused_avg,IF \
     CDEF:used_stk=used_nnl,sused_nnl,+ \
     AREA:used_stk#bff7bf \
     LINE1:used_stk#00e000:swap      \
     GPRINT:sused_avg:AVERAGE:"avg\:%4.2lf%s"   \
     GPRINT:sused_min:MIN:"min\:%4.2lf%s"       \
     GPRINT:sused_max:MAX:"max\:%4.2lf%s"      \
     GPRINT:sused_avg:LAST:"cur\:%4.2lf%s\n" \
     AREA:used_nnl#bfbfff \
     LINE1:used_nnl#0000ff:used      \
     GPRINT:used_avg:AVERAGE:"avg\:%4.2lf%s"   \
     GPRINT:used_min:MIN:"min\:%4.2lf%s"       \
     GPRINT:used_max:MAX:"max\:%4.2lf%s"      \
     GPRINT:used_avg:LAST:"cur\:%4.2lf%s\n"

}

#-----------------------------------------------------------
#CPUのデータを描画する
#-----------------------------------------------------------
cpu_plot()
{
#引数1:CPU番号
#引数2:期間(0:HalfHourly1:Hourly,2:Daily,3:Weekly)

case "$2" in
        "0" )
        TERM=HalfHourly
        START="-31minutes" ;;
        "1" )
        TERM=Hourly
        START="-61minutes" ;;
        "2" )
        TERM=Daily
        START="-25hours" ;;
        "3" )
        TERM=Weekly
        START="-8days" ;;
        "" )
        exit ;;
esac

#画像ファイル名
PNGNAME=CPU

#CPUのデータが出力される場所
RRDDATAFILE=${RRDDATAPATH}cpu-$1/

#画像を作成
rrdtool graph --imgformat PNG ${OUTPUTDATAPATH}${PNGNAME}$1_${TERM}.png \
     --start ${START}  --width 640 --height 100 \
     -n DEFAULT:0:"Bitstream Vera Sans" \
     --vertical-label "%" \
     --rigid --upper-limit 100 \
     --title ${PNGNAME}$1${TERM} \
     DEF:idle_min=${RRDDATAFILE}cpu-idle.rrd:value:MIN \
     DEF:idle_avg=${RRDDATAFILE}cpu-idle.rrd:value:AVERAGE \
     DEF:idle_max=${RRDDATAFILE}cpu-idle.rrd:value:MAX \
     CDEF:idle_nnl=idle_avg,UN,0,idle_avg,IF \
     DEF:wait_min=${RRDDATAFILE}cpu-wait.rrd:value:MIN \
     DEF:wait_avg=${RRDDATAFILE}cpu-wait.rrd:value:AVERAGE \
     DEF:wait_max=${RRDDATAFILE}cpu-wait.rrd:value:MAX \
     CDEF:wait_nnl=wait_avg,UN,0,wait_avg,IF \
     DEF:nice_min=${RRDDATAFILE}cpu-nice.rrd:value:MIN \
     DEF:nice_avg=${RRDDATAFILE}cpu-nice.rrd:value:AVERAGE \
     DEF:nice_max=${RRDDATAFILE}cpu-nice.rrd:value:MAX \
     CDEF:nice_nnl=nice_avg,UN,0,nice_avg,IF \
     DEF:user_min=${RRDDATAFILE}cpu-user.rrd:value:MIN \
     DEF:user_avg=${RRDDATAFILE}cpu-user.rrd:value:AVERAGE \
     DEF:user_max=${RRDDATAFILE}cpu-user.rrd:value:MAX \
     CDEF:user_nnl=user_avg,UN,0,user_avg,IF \
     DEF:system_min=${RRDDATAFILE}cpu-system.rrd:value:MIN \
     DEF:system_avg=${RRDDATAFILE}cpu-system.rrd:value:AVERAGE \
     DEF:system_max=${RRDDATAFILE}cpu-system.rrd:value:MAX \
     CDEF:system_nnl=system_avg,UN,0,system_avg,IF \
     DEF:softirq_min=${RRDDATAFILE}cpu-softirq.rrd:value:MIN \
     DEF:softirq_avg=${RRDDATAFILE}cpu-softirq.rrd:value:AVERAGE \
     DEF:softirq_max=${RRDDATAFILE}cpu-softirq.rrd:value:MAX \
     CDEF:softirq_nnl=softirq_avg,UN,0,softirq_avg,IF \
     DEF:interrupt_min=${RRDDATAFILE}cpu-interrupt.rrd:value:MIN \
     DEF:interrupt_avg=${RRDDATAFILE}cpu-interrupt.rrd:value:AVERAGE \
     DEF:interrupt_max=${RRDDATAFILE}cpu-interrupt.rrd:value:MAX \
     CDEF:interrupt_nnl=interrupt_avg,UN,0,interrupt_avg,IF \
     DEF:steal_min=${RRDDATAFILE}cpu-steal.rrd:value:MIN \
     DEF:steal_avg=${RRDDATAFILE}cpu-steal.rrd:value:AVERAGE \
     DEF:steal_max=${RRDDATAFILE}cpu-steal.rrd:value:MAX \
     CDEF:steal_nnl=steal_avg,UN,0,steal_avg,IF \
     CDEF:steal_stk=steal_nnl \
     CDEF:interrupt_stk=interrupt_nnl,steal_stk,+ \
     CDEF:softirq_stk=softirq_nnl,interrupt_stk,+ \
     CDEF:system_stk=system_nnl,softirq_stk,+ \
     CDEF:user_stk=user_nnl,system_stk,+ \
     CDEF:nice_stk=nice_nnl,user_stk,+ \
     CDEF:wait_stk=wait_nnl,nice_stk,+ \
     CDEF:idle_stk=idle_nnl,wait_stk,+ \
     AREA:idle_stk#ffffff \
     LINE1:idle_stk#ffffff:idle      \
     GPRINT:idle_avg:AVERAGE:"avg\:%3.2lf%s"   \
     GPRINT:idle_min:MIN:"min\:%3.2lf%s"       \
     GPRINT:idle_max:MAX:"max\:%3.2lf%s"      \
     GPRINT:idle_avg:LAST:"cur\:%3.2lf%s\n"      \
     AREA:wait_stk#ffebbf \
     LINE1:wait_stk#ffb000:wait      \
     GPRINT:wait_avg:AVERAGE:"avg\:%3.2lf%s"   \
     GPRINT:wait_min:MIN:"min\:%3.2lf%s"       \
     GPRINT:wait_max:MAX:"max\:%3.2lf%s"      \
     GPRINT:wait_avg:LAST:"cur\:%3.2lf%s\n"      \
     AREA:nice_stk#bff7bf \
     LINE1:nice_stk#00e000:nice      \
     GPRINT:nice_avg:AVERAGE:"avg\:%3.2lf%s"   \
     GPRINT:nice_min:MIN:"min\:%3.2lf%s"       \
     GPRINT:nice_max:MAX:"max\:%3.2lf%s"      \
     GPRINT:nice_avg:LAST:"cur\:%3.2lf%s\n"      \
     AREA:user_stk#bfbfff \
     LINE1:user_stk#0000ff:user      \
     GPRINT:user_avg:AVERAGE:"avg\:%3.2lf%s"   \
     GPRINT:user_min:MIN:"min\:%3.2lf%s"       \
     GPRINT:user_max:MAX:"max\:%3.2lf%s"      \
     GPRINT:user_avg:LAST:"cur\:%3.2lf%s\n"      \
     AREA:system_stk#ffbfbf \
     LINE1:system_stk#ff0000:system    \
     GPRINT:system_avg:AVERAGE:"avg\:%3.2lf%s"   \
     GPRINT:system_min:MIN:"min\:%3.2lf%s"       \
     GPRINT:system_max:MAX:"max\:%3.2lf%s"      \
     GPRINT:system_avg:LAST:"cur\:%3.2lf%s\n"      \
     AREA:softirq_stk#ffbfff \
     LINE1:softirq_stk#ff00ff:softirq   \
     GPRINT:softirq_avg:AVERAGE:"avg\:%3.2lf%s"   \
     GPRINT:softirq_min:MIN:"min\:%3.2lf%s"       \
     GPRINT:softirq_max:MAX:"max\:%3.2lf%s"      \
     GPRINT:softirq_avg:LAST:"cur\:%3.2lf%s\n"      \
     AREA:interrupt_stk#e7bfe7 \
     LINE1:interrupt_stk#a000a0:interrupt \
     GPRINT:interrupt_avg:AVERAGE:"avg\:%3.2lf%s"   \
     GPRINT:interrupt_min:MIN:"min\:%3.2lf%s"       \
     GPRINT:interrupt_max:MAX:"max\:%3.2lf%s"      \
     GPRINT:interrupt_avg:LAST:"cur\:%3.2lf%s\n"      \
     AREA:steal_stk#bfbfbf \
     LINE1:steal_stk#000000:steal     \
     GPRINT:steal_avg:AVERAGE:"avg\:%3.2lf%s"   \
     GPRINT:steal_min:MIN:"min\:%3.2lf%s"       \
     GPRINT:steal_max:MAX:"max\:%3.2lf%s"      \
     GPRINT:steal_avg:LAST:"cur\:%3.2lf%s\n"
}

#実行
cpu_plot 0 0 > /dev/null
cpu_plot 0 1 > /dev/null
cpu_plot 1 0 > /dev/null
cpu_plot 1 1 > /dev/null
cpu_plot 2 0 > /dev/null
cpu_plot 2 1 > /dev/null

memory_plot 0 > /dev/null
memory_plot 1 > /dev/null

interface_plot 0 > /dev/null
interface_plot 1 > /dev/null

opensim_plot 0 0 > /dev/null
opensim_plot 0 1 > /dev/null
opensim_plot 0 2 > /dev/null
opensim_plot 0 3 > /dev/null
opensim_plot 1 0 > /dev/null
opensim_plot 1 1 > /dev/null
opensim_plot 1 2 > /dev/null
opensim_plot 1 3 > /dev/null

1時間と1週間ものは、1時間ごとに実行するので、スクリプトを分けます。

[root@foo ~]# vi /home/takeshich/rrdgraph_w.sh
#!/bin/bash
#1時間おきに日毎と週毎のを作成

#timezoneをいれないと曜日の表示がおかしいようなので
TZ=Asia/Tokyo
. /home/takeshich/rrdgraph.sh

cpu_plot 0 2 > /dev/null
cpu_plot 0 3 > /dev/null
cpu_plot 1 2 > /dev/null
cpu_plot 1 3 > /dev/null
cpu_plot 2 2 > /dev/null
cpu_plot 2 3 > /dev/null

memory_plot 2 > /dev/null
memory_plot 3 > /dev/null

interface_plot 2 > /dev/null
interface_plot 3 > /dev/null

opensim_plot 2 0 > /dev/null
opensim_plot 2 1 > /dev/null
opensim_plot 2 2 > /dev/null
opensim_plot 2 3 > /dev/null
opensim_plot 3 0 > /dev/null
opensim_plot 3 1 > /dev/null
opensim_plot 3 2 > /dev/null
opensim_plot 3 3 > /dev/null

作成した2つのスクリプトを定期実行させるためにcrontabを編集します。1時間おきのものは毎時4分に実行することとします。rrdgraph.shが10分おきに実行されているので被らないようにするためです。

[root@foo ~]# crontab -e
*/10  *  *  *  * /home/takeshich/rrdgraph.sh
04 0-23/1 * * * /home/takeshich/rrdgraph_w.sh

これで定期的に以下のようにグラフが出力されるようになります。

※PWSMemoryの単位がおかしいなぁ。

最後に

あとは、HTMLファイルを作成してあげて、Apacheなどのwebサーバで、Basic認証をかけて限定公開をすれば、パフォーマンスを監視する環境が出来上がります。
今回は、HTMLファイル、Apacheの設定やSSLの手順、Basic認証については記述しません。検索すれば、すぐにその方法を知ることができます。あくまでもこのエントリはOpenSimのパフォーマンスがターゲットです。
次は、もうちょっとグラフをきちんとしてものにすることとパフォーマンステストを実施してみて、結果を分析するということをしたいと思っています。

*1:SIMMegaRegion(2x2)で、Prims数: 12586+3061+10473+17323=43443、隣接するSIMがある。

*2:勘違いしていたようで、自分で追加したっぽいです。

*3:http://opensimulator.org/wiki/XSimStatus

*4:http://www.collectd.org/

*5:http://oss.oetiker.ch/rrdtool/