HP-UX General
1819809 メンバー
2736 オンライン
109607 解決策
新規ポスト

共有ライブラリの使用メモリの調べ方

 
W_Ha
時折のアドバイザー

共有ライブラリの使用メモリの調べ方

いつも勉強させていただいてます。

共有ライブラリ(.sl)の使用メモリを知りたいのですが、何か調べるコマンドがあるのでしょうか?

それとも、そもそも通常のプロセスと同じような考え方ではないのでしょうか(仮想メモリと常駐メモリが存在するなどと言った感じでは無いのでしょうか)?

何か参考になるドキュメントなどを教えて頂けると有難いです(できれば日本語)。

8件の返信8
テレコム担当者
尊敬されているコントリビューター

共有ライブラリの使用メモリの調べ方

Glance がインストールされていれば、Glance で Select process で

プロセス番号を指定して Memory Regions を見ます。

Memory Regions PID: 23289, glance PPID: 15621 euid: 0 User: foo

Type RefCt RSS VSS Locked File Name

--------------------------------------------------------------------------------

NULLDR/Shared 142 4kb 4kb 0kb

TEXT /Shared 2 332kb 444kb 0kb

DATA /Priv 1 1.6mb 1.7mb 0kb

MEMMAP/Priv 1 4kb 8kb 0kb

MEMMAP/Priv 1 0kb 4kb 0kb

Text RSS/VSS:332kb/444kb Data RSS/VSS:1.6mb/1.7mb Stack RSS/VSS: 64kb/128kb

Shmem RSS/VSS: 10mb/ 18mb Other RSS/VSS:4.7mb/6.8mb

上記は

Shmem RSS/VSS: 10mb/ 18mb です。

RSS -> resident size(physical memory上のメモリサイズ)

VSS -> Virtual size (Virtual memory上のメモリサイズ)

W_Ha
時折のアドバイザー

共有ライブラリの使用メモリの調べ方

テレコム担当者様早速の回答ありがとうございます。

残念ながらGlanceが使えない環境なので、何かコマンドか、Cでプログラムを作って求めることはできないものかと、調べているのです。

そもそも本来の目的としてはGlanceで表示される1プロセス分のRSSと同じ物を求めたいのですがGlanceのヘルプに載っている、算出式には

RSS = sum of private region pages +

(sum of shared region pages /

number of references)

となっているので、

1、対象プロセスの使用メモリを求める。

2、プロセスが使用している全共有ライブラリを探し出す。

3、各共有ライブラリのメモリ使用量を求める。

4、各共有ライブラリを参照しているプロセス数を求める。

と言うことをしないといけないと思うのですが、1の方法は分かるのですが、2〜4は難しそうなので、10歩譲って、単純に指定した共有ライブラリのメモリ使用量を求めるコマンドでもないものかと考えています。

nadachi
レギュラーアドバイザー

共有ライブラリの使用メモリの調べ方

> 残念ながらGlanceが使えない環境なので、何か

> コマンドか、Cでプログラムを作って求めること

> はできないものかと、調べているのです。

Glanceが一番便利なのですが、pstat(2)の応用で、pstat_getprocvm()が使えそうですが。以下はざっと作ったサンプルですが、

/*

cc with -D_PSTAT64

int pstat_getprocvm(

struct pst_vm_status *buf,

size_t elemsize,

size_t elemcount,

int index);

*/

#include

#include

#include

main(argc, argv)

int argc;

char *argv[];

{

 pid_t target;

struct pst_vm_status v;

int i, ret, idx;

target = atoi(argv);

printf("pid = %d\n", target == 0 ? getpid() : target);

idx = 0;

while ((ret = pstat_getprocvm(

        (struct pst_vm_status *)&v,

(size_t)sizeof(struct pst_vm_status),

(size_t)target,

idx)) > 0) {

switch(v.pst_type) {

case PS_NOTUSED :

printf("NOT USED: "); break;

case PS_USER_AREA :

printf("U-AREA: "); break;

case PS_TEXT :

printf("TEXT: "); break;

case PS_DATA :

printf("DATA: "); break;

case PS_STACK :

printf("STACK: "); break;

case PS_SHARED_MEMORY :

  printf("SHARED_MEMORY: "); break;

case PS_NULLDEREF :

printf("NULLDEREF: "); break;

case PS_IO :

printf("IO: "); break;

case PS_MMF :

   printf("MMF: "); break;

case PS_GRAPHICS :

printf("GRAPHICS: "); break;

case PS_GRAPHICS_DMA :

printf("GRAPHICS_DMA: "); break;

}

if (v.pst_flags & PS_MEMORY_LOCKED)

printf("MEMORY_LOCKED ");

if (v.pst_flags & PS_EXECUTABLE)

printf("EXECUTABLE ");

if (v.pst_flags & PS_SHARED)

printf("SHARED ");

if (v.pst_flags & PS_SHARED_LIBRARY)

printf("SHARED_LIBRARY");

printf("\n");

printf("\t0x%llx.0x%llx ",

v.pst_space, v.pst_vaddr);

printf("refct:%lld phys_pages:%lld length:%lld",

v.pst_refcnt, v.pst_phys_pages, v.pst_length);

printf("\n");

++idx;

}

}

$ cc -D_PSTAT64 procvm.c

$ a.out

$ ./a.out  # 引数なしは自分自身。

pid = 9734

NULLDEREF: SHARED

0x8321c00.0x0 refct:117 phys_pages:1 length:1

TEXT: EXECUTABLE SHARED

0x8321c00.0x1000 refct:2 phys_pages:2 length:3

DATA:

0x54d6000.0x40001000 refct:1 phys_pages:6 length:7

MMF:

0x54d6000.0x6ffd0000 refct:1 phys_pages:0 length:1

MMF: SHARED_LIBRARY

0x54d6000.0x6ffd1000 refct:1 phys_pages:1 length:1

MMF:

0x54d6000.0x6ffd2000 refct:1 phys_pages:4 length:4

MMF: SHARED_LIBRARY

0x54d6000.0x6ffd6000 refct:1 phys_pages:8 length:8

MMF:

0x54d6000.0x6ffde000 refct:1 phys_pages:6 length:11

MMF: SHARED_LIBRARY

0x54d6000.0x6ffe9000 refct:1 phys_pages:1 length:1

...

 なんていう風に出ます。 (これは 11.11でやりました。) phys_pages と length の単位はおそらく page (4kbytes) でしょう。

 上で、

MMF: SHARED_LIBRARY

の部分が、共有ライブラリのために割り付けた  memory mapped file の部分でしょう。

( どの共有ライブラリファイルか、に対応つけるのはちょっと難しそうです。pstat()の他の関数と組み合わせれば出来るかも知れませんが。)

参考まで。

W_Ha
時折のアドバイザー

共有ライブラリの使用メモリの調べ方

nadachiさんありがとうございます。

nadachiさんに教えていただいたソースを元に、色々試してみて、当初の目的だった glanceのRSS(と近い値)を求めることができました。

近い値なのは、参照数で割り算した時の小数点以下の四捨五入(もしくは切り捨て)のタイミングのせいかと思っています。

ですが疑問が出てきました。求めたRSSはglanceの出力と比べて確認しているのですが、中には私の求めたRSSと全く桁外れな値の物があります。

具体的にはあるプロセス(Oracleのサーバープロセス)のglanceでのRSSは21.8Gbyteのものが、私の求めたものでは2Gbyteと、桁違いな値の場合があります。

RSSは瞬時値だと思いますので連続的に監視してもglanceのRSSは21Gbyte辺りで推移していて、2Gbyteまで変動したりはしていません。

ですので私の算出方法が間違っているのかと現在調べているところなのです。

私の計算方法はpstat_getprocvm()関数でidx毎に取得した、v.pst_phys_pages を v.pst_refcntで単純に割り算して、全てのidxの値を合計したものをRSSとしています。

v.pst_type(TextとかData、Stack、その他)によって v.pst_refcnt(参照数?)で割り算しない物があるのかとか思うのですが…。

気になったのが、nadachiさんのa.outの実行例でTypeが v.pst_typeが TEXTの参照数が2というのは何故なのでしょう?このTextとはプロセスのプログラムコード部分だと思うのですが、共有しているとは思わないのですが…。

どなたか答えでなくとも、なにかご意見などでもありましたら、教えて頂けると助かります。

W_Ha
時折のアドバイザー

共有ライブラリの使用メモリの調べ方

すみません具体例の所のメモリサイズの単位を間違えていました。GbyteはMByteの間違いです。

>>具体的にはあるプロセス(Oracleのサーバープロセ>>ス)のglanceでのRSSは21.8Gbyteのものが、私の求>>めたものでは2Gbyteと、桁違いな値の場合がありま>>す。

nadachi
レギュラーアドバイザー

共有ライブラリの使用メモリの調べ方

>気になったのが、nadachiさんのa.outの実行例

>でTypeが v.pst_typeが TEXTの参照数が2と

>いうのは何故なのでしょう?

この部分の表示は Glance でも同じですね。

"Shared text"を実現する仕組みに関係していると思います。というのは、

$ cc -D_PSTAT64 -N procvm.c

/usr/ccs/bin/ld: (Warning) At least one PA 2.0 object file (procvm.o) was detect

ed. The linked output may not run on a PA 1.x system.

 というオプション付でコンパイルして、"shared"の

属性を外すと、

$ file a.out

a.out: PA-RISC2.0 executable dynamically linked -not stripped

$ ./a.out

pid = 4993

NULLDEREF: SHARED

0xff0e800.0x0 refct:86 phys_pages:1 length:1

TEXT: EXECUTABLE

0xff0e800.0x1000 refct:1 phys_pages:3 length:3

DATA:

0xff0e800.0x4000 refct:1 phys_pages:6 length:8

MMF:

0xff0e800.0x7b035000 refct:1 phys_pages:0 length:1

 "text"の type はEXECUTABLEだけになり、refcntは 1 になりますから。

 
nadachi
レギュラーアドバイザー

共有ライブラリの使用メモリの調べ方

> 具体的にはあるプロセス(Oracleのサーバー

> プロセス)のglanceでのRSSは21.8Gbyteのもの

> が、私の求めたものでは2Gbyteと、桁違いな値

> の場合があります。

- Glance のほうが大きな値だ。

 - 21.8Gbytes と 2Gbytes。

の2点から、一つだけ気になることがあります。pstat()で報告された "page数" もこれを裏付けていますか? というのは、

$ more giga.c

#include

main()

{

unsigned long size, pages;

unsigned int a;

size = (long)22 * (long)(1024 * 1024 * 1024);

printf("%llu bytes\n", size);

pages = size / 4096;

printf("%llu pages\n", pages);

a = 4096 * pages;

printf("%u bytes (converted from pages)\n", a);

}

 というプログラムで、

$ cc +DD64 giga.c

$ ./a.out

23622320128 bytes

5767168 pages

2147483648 bytes (converted from pages)

 と表示が出ます。これは何かというと、

size = (long)22 * (long)(1024 * 1024 * 1024);

は 22Gbytes のバイト数を求めている。

  pages = size / 4096;

1 page = 4096bytesですから、これは22Gbytesの

page数になる。pstat()で返される値はこれくらいのオーダーになる。

  a = 4096 * pages;

は、ページ数に 4096をかけて byte数換算をしようと

しているところですが、"unsigned int a" と

なっている。ですので、

23622320128 bytes # 22Gbytesのバイト数

5767168 pages   # ページ数

2147483648 bytes (converted from pages)

  # ページ数から計算したバイト数

で、"ページ数から計算したバイト数"は22Gbytesではなく、2Gbytes になってしまう。

 お気に触るかも知れませんが、"22Gbytesと2Gbytes" という数の組み合わせでは、この点が気になります。
hazelwood
信頼あるコントリビューター

共有ライブラリの使用メモリの調べ方

nadachiさんの指摘が的を得ているものと思いますが、分かりにくいので、解説を入れます。

このサンプルプログラムは、+DD64オプションつきでコンパイルしているところがポイントで、これでLP64モデルでコンパイルされ、long=64bit, int=32bitになります。

unsigned londで定義されているsizeは、64bitデータなので、4G超の数値も扱えますが、unsigned intのaは32bitなので、最大4Gに制限されます。

4096 * pagesは(pagesがunsigned longなのでキャストされて)、正しい(期待する)計算結果になりますが、これをa(=unsigned int)に代入する際に、上位ビットが切り捨てられます。この結果、aには2Gの数値のみが残ります。

私がこの類のコードを書くときは、バイト単位のサイズは必要ではないので、最初から、pages*4でKB単位にするか、pages/256でMB単位にしてしまいます。これで、unsigned intでもほとんどのケースでオーバーフローを気にしなくてよくなります。