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

kubo39's blog

ただの雑記です。

日記: 10/11~12あたり

メモリ情報

D言語でプロセス・システムのメモリ使用量をとりたいときどうするんだ、みたいな話があって、自分だとmallinfo(3)とかで

import std.stdio;

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 main()
{
    auto mi = mallinfo();
    writefln("Total non-mmapped bytes (arena): %d", mi.arena);
    ...
}

みたいなかんじでutilを作ってやったりしてました。

https://dlang.org/spec/interfaceToC.html のとおり extern(C) 内に書いたやつはDコンパイラがいいかんじにmangleとか呼び出し規約とかみてくれるのでわりと意識せずに書けます。

mallinfo(3)はglibcにあるので別共有ライブラリにリンクする必要もないし楽です。

% readelf -s /lib64/libc.so.6| grep mallinfo
  1199: 0000000000081b60   258 FUNC    GLOBAL DEFAULT   12 __libc_mallinfo@@GLIBC_2.2.5
  1446: 0000000000081b60   258 FUNC    WEAK   DEFAULT   12 mallinfo@@GLIBC_2.2.5
  1063: 000000000007bf90   278 FUNC    LOCAL  DEFAULT   12 int_mallinfo
  3830: 0000000000081b60   258 FUNC    LOCAL  DEFAULT   12 __mallinfo
  5867: 0000000000081b60   258 FUNC    GLOBAL DEFAULT   12 __libc_mallinfo
  7228: 0000000000081b60   258 FUNC    WEAK   DEFAULT   12 mallinfo

別プロセスのが欲しいときとかだと /proc/<PID>/statm をファイルとして開いたりというかんじでした。

まあこういうのやはりdubにパッケージがあって resusage というのを使えば良さそうです。 ある程度ポータブルに動くのでこういうの使ったほうがいいですね。

Linuxだとシステム全体のメモリ使用統計はsysinfo(2)使ってて、プロセス単位だと /proc/<PID>/stat をパースしてます。メモリだけならstatmでいいんじゃないの?と思うんですがCPU側とかの統計もとっててstatを共通のインターフェースとして使ってるんですよね。

リンクの話

D言語、というかdmdの吐くバイナリのリンク処理ってどうなってるの、みたいな。

まず環境

% cat /etc/{redhat,centos}-release
CentOS Linux release 7.1.1503 (Core)
CentOS Linux release 7.1.1503 (Core)
% uname -mrv
3.10.0-229.14.1.el7.x86_64 #1 SMP Tue Sep 15 15:05:51 UTC 2015 x86_64

わりと一般的ですね?

dmdにおいて、リンク処理はccをたたいて実現しています。

% dmd -v hello.d| tail -1
cc hello.o -o hello -m64 -L/home/hiroki.noda/dlang/dmd-2.071.1/linux/bin64/../lib64 -Xlinker --export-dynamic -Xlinker -Bstatic -lphobos2 -Xlinker -Bdynamic -lpthread -lm -lrt -ldl

ccは手元の環境だとGCCです。リンク処理はGNU ldを使ってます。GCCが内部でldを呼ぶときはデフォルトでlibc.soとかもろもろを動的リンクするようになっています。ここではさらに明示的にlibpthread.soだとかlibm.soだとかがされてますね。

% cc --version
cc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9)

% ld --version
GNU ld version 2.23.52.0.1-30.el7_1.2 20130226

lddで調べてみるともろもろ動的リンクされてます。

% ldd hello
        linux-vdso.so.1 =>  (0x00007ffc4c908000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f2e461e5000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f2e45ee2000)
        librt.so.1 => /lib64/librt.so.1 (0x00007f2e45cda000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f2e45ad6000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f2e458bf000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f2e454fe000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f2e46411000)