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

中年engineerの独り言 - crumbjp

LinuxとApacheの憂鬱

MongoDB2.4新機能 Working Set Analyzer

mongodb

Working Set Analyzer

MongoDB2.4からはサーバリソースの管理・評価にAnalyzerが使えるようになりました。

利用方法は既存のコマンドdb.serverStatus()を叩くだけです。

マニュアル
翻訳
workingSet New in version 2.4. Example:output of the workingSet fields. Note: The workingSet data is only included in the output of serverStatus if explicitly enabled. To return the workingSet use one of the following commands:
db.serverStatus( { workingSet: 1 } )
db.runCommand( { serverStatus: 1, workingSet: 1 } )
working Set バージョン2.4新機能 workingSet項目の出力はserverStatusにworkingSetパラメータを明示的に指定した場合に出力されます。
serverStatus.workingSet
workingSet is a document that contains values useful for estimating the size of the working set, which is the amount of data that MongoDB uses actively. workingSet uses an internal data structure that tracks pages accessed by mongod.
serverStatus.workingSet
workingSet はMongoDBが現在利用しているデータ量などワーキングセットサイズの見積もりに利用できる情報を含むドキュメントです。workingSetはmongodが利用しているアクセスページ追跡用の内部データです。
serverStatus.workingSet.note
note is a field that holds a string warning that the workingSet document is an estimate.
serverStatus.workingSet.note
note はworkingSetドキュメントが見積もりに過ぎないという警告メッセージです。
serverStatus.workingSet.pagesInMemory
pagesInMemory contains a count of the total number of pages accessed by mongod over the period displayed in overSeconds. The default page size is 4 kilobytes: to convert this value to the amount of data in memory multiply this value by 4 kilobytes.
If your total working set is less than the size of physical memory, over time the value of pagesInMemory will reflect your data size. Conversely, if your data set is greater than the size of the physical RAM, this number will reflect the total size of physical RAM.

Use pagesInMemory in conjunction with overSeconds to help estimate the actual size of the working set.
serverStatus.workingSet.pagesInMemory
はmongodがoverSecondsフィールドが示す秒数間にアクセスしたページの総数です。ページサイズはデフォルト4KBでページ数×4KBでデータ量になります。
もし総ワーキングセットサイズがサーバの物理メモリ量を下回った場合、pageInMemoryの値は扱っている(あなたの)データ量を示すだろう。
逆に扱っているデータ量が物理メモリサイズを超えた場合、この値は物理メモリ量を示すだろう。

実際のワーキングセットサイズを見積もる為にpageInMemoryとoverSecondsを使ってください。
serverStatus.workingSet.computationTimeMicros
computationTimeMicros reports the amount of time the mongod instance used to compute the other fields in the workingSet section.
Reporting on workingSet may impact the performance of other operations on the mongod instance because MongoDB must collect some data within the context of a lock. Ensure that automated monitoring tools consider this metric when determining the frequency of collection for workingSet.
serverStatus.workingSet.computationTimeMicros
computationTimeMicrosはmongodがworkingSetドキュメントを算出するのに掛った時間です。
workingSetレポートを作る処理はmongodのパフォーマンスに影響を与え得る。それはMongoDBはコンテキストをロックしてデータを収集しなければならないからだ。頻繁にworkingSet情報を監視しようとする自動モニタリングツールはこの事を考慮する事。
serverStatus.workingSet.overSeconds
overSeconds returns the amount of time elapsed between the newest and oldest pages tracked in the pagesInMemory data point.
If overSeconds is decreasing, or if pagesInMemory equals physical RAM and overSeconds is very small, the working set may be much larger than physical RAM.
When overSeconds is large, MongoDB’s data set is equal to or smaller than physical RAM.
serverStatus.workingSet.overSeconds
overSecondsはpageInMemoryに含まれる最古のページと最新のページの差(つまりpageInMoeoryカウント期間)である。
もしoverSecondsが減少するかpagesInMemoryがサーバ物理メモリ量と等しくoverSecondsが非常に小さい場合、ワーキングセットサイズは物理メモリ量よりずっと大きい(つまりメモリーが足りない)事を意味する。
overSecondsが大きい場合、MongoDBのデータセットは物理メモリ量以下である。

実際の評価方法

まずはメモリー情報を取る。
$ cat /proc/meminfo  | head
MemTotal:         498800 kB
 :
 :
物理メモリーは487MBです。(VMなので・・・)
RS:PRIMARY> db.serverStatus().mem
{
        "bits" : 64,
        "resident" : 127,
        "virtual" : 11292,
        "supported" : true,
        "mapped" : 5262,
        "mappedWithJournal" : 10524
}
resident
実際占有しているメモリー(MB)
つまり127MBのメモリーを使っている
virtual
仮想メモリーとして取得しているサイズ(MB)
つまり11GB程度。
mapped
データファイルのマッピング量(MB)
mmapで5GB程度マップしている。
mappedWithJournal
journalも含んだマッピング量いつもmappedの倍になる。
という事でmongodは127MBのメモリーを使っている様です。
データファイルは全部データで埋まってる訳では無く(これから使う領域もある)データが入っていてもアクティブに利用されていない場合もあるので ここでマッピングファイルが10GBあるのにメモリー127MBじゃ全然足りないじゃん!というのは早計です。
次にworkingSetを情報を取る
RS:PRIMARY> db.serverStatus({workingSet:1}).workingSet
{
        "note" : "thisIsAnEstimate",
        "pagesInMemory" : 114700,
        "computationTimeMicros" : 33046,
        "overSeconds" : 1189
}
pageInMemory
約448MB
overSeconds
約20分
そんな訳で
pageInMemoryは物理メモリー量に近い反面、overSecondsは十分長い。
つまりモリーに載り切らない程のデータを扱ってはいるものの、アクセス頻度はそれ程でも無くメモリー不足が逼迫している程でもない。とMongoDBは解釈しているが
127MB以外はOSによってスワップアウトされておりやっぱりメモリーが足りてない!
OSで別に動いてるプロセスを止めるかメモリーを足すべき
と解釈できます。

追記:やはり解せない!
MongoDBのAnalyzerはオンメモリー判定にちゃんとmincore()を使っており、若干のタイミングのずれによって誤差が出る位なら兎も角、127MB -> 448MBという誤差にはならないハズ!!
となると疑うべきは
  • Analyzerがチェックしているページのポインタがずれてる(Mongoのバグ)
   or
  • mincoreが間違った結果を返す事がある?(OS or VMのバグ)
ちなみに、ページサイズは4kbで間違いない・・・
$ getconf PAGESIZE
4096
|<<
要、更に検証・・・
<<
*** 追記
アクセス量を増やした所、こうなりました。
>|javascript|
RS:PRIMARY> db.serverStatus({workingSet:1}).workingSet
{
        "note" : "thisIsAnEstimate",
        "pagesInMemory" : 152834,
        "computationTimeMicros" : 23162,
        "overSeconds" : 925
}
pageInMemory
597MB
overSeconds
約15分
overSecondsは減りましたね。ただ充分な負荷やバラツキが再現できていないのか思ったより減りません。 あとpageInMemoryが明らかに物理メモリーサイズを超えました・・・なぜだろう??