kubo39's blog

ただの雑記です。

コードを書き換えずに実行時のメモリ使用量を観測したい

元のプログラムを書き換えることなく実行中にメモリ使用量をみることを考える。

libcの関数、例えば free(3) にフックを仕込んでみたらどうだろうか。

こういうコードを書く。

import core.stdc.stdio : printf;
import core.sys.linux.dlfcn : dlsym, RTLD_NEXT;

extern (C)
{
    struct mallinfo_
    {
        int arena;  /* Non-mmapped space allocated (bytes) */
        int ordblks;  /* Number of free chunks */
        int smblks;  /* Number of free fastbin blocks */
        int hblks;  /* Number of mmapped regions */
        int hblkhd;  /* Space allocated in mmapped regions (bytes) */
        int usmblks;  /* Maximum total allocated space (bytes) */
        int fsmblks;  /* Space in freed fastbin blocks (bytes) */
        int uordblks;  /* Total allocated space (bytes) */
        int fordblks;  /* Total free space (bytes) */
        int keepcost;  /* Top-most, releasable space (bytes) */
    }

    mallinfo_ mallinfo();

    void free(void *ptr)
    {
        auto info = mallinfo();
        printf("mallinfo arena:  %d.\n", info.arena);
        auto original = cast(void function(void*)) dlsym(RTLD_NEXT, "free");
        return original(ptr);
    }
}

いい感じに観測できていそうだ。いろいろオプションがついているが、-sharedは共有リンクライブラリを作成するためにつけており、-defaultlibや-fPICはGCC hardenedのためこうしているだけでこれらは本質的な部分ではない。

(dmd-2.072.0)( ՞ਊ ՞) :~/dev/dlang $ dmd -shared -fPIC -defaultlib=libphobos2.so freewrap.d
(dmd-2.072.0)( ՞ਊ ՞) :~/dev/dlang $ LD_PRELOAD=./freewrap.so dmd -fPIC -defaultlib=libphobos2.so hello.d
malloc info arena:  135168.
malloc info arena:  135168.
malloc info arena:  135168.
...
malloc info arena:  2195456.
malloc info arena:  2195456.
malloc info arena:  2195456.

originalのfree(3)を実行する直前のメモリ使用量を観測できた。

LD_PRELOADを使った方法なので、共有リンクライブラリで定義されている関数でしか使えないが、それなりに役に立つ可能性はありそう。