Solaris 10:仮想メモリが使い果たされました。

Solaris 10:仮想メモリが使い果たされました。

私たちのチームはすべてLinuxまたはMacOSでのみ作業しているプログラマーですが、顧客はSolaris 10を使用しているので、そこで動作するにはコードが必要です。だから私たちはテストのために古いSunFire V240とリースされたSolaris 10 VMを見つけました。

コードはVMで正しくコンパイルされますが、SunFireでは失敗します。私たちのコードには、ビルドの一部として自動生成された巨大なC ++ファイルがあります。コンパイルできない巨大なファイルです。次のメッセージで失敗します。virtual memory exhausted: Not enough space

わかりません。 SunFireには8GBのRAMがあり、コンパイルが1.2GBを少し超えると仮想メモリ消費が発生します。他の重要なことは実行されません。以下は、ほぼ失敗に近いメモリ統計です。

使用prstat -s size:

SIZE (virtual memory): 1245 MB
RSS  (real memory):    1200 MB

によると、echo "::memstat" | mdb -kまだ多くのメモリを使用することができます。

Free (cachelist) is 46%
Free (freelist)  is 26% of total.

コンパイルが失敗する前に、すべてのユーザープロセスはRAMの約17%を使用しました。 (障害発生後、ユーザーのRAM使用量は2%に低下しました。)これは他のRAM使用量と一致します。 (1.2GB /8.0GB ~= 15%)

swap -lレポートによると、スワップは完全に使用されていません。

その他の詳細:

私たちは64ビット用にコンパイルされたg ++ 6.1.0を使って構築しました。 -m64 フラグをコンパイラーに渡すかどうかに関係なく失敗します。

# uname -a 
SunOS servername 5.10 Generic_147440-27 sun4u sparc SUNW,Sun-Fire-V240

VM および SunFire のシステム制限は、次のように設定されます。

>ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
open files                      (-n) 256
pipe size            (512 bytes, -p) 10
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 29995
virtual memory          (kbytes, -v) unlimited

(using su)>rctladm -l
...
process.max-address-space   syslog=off     [ lowerable deny no-signal bytes ]
process.max-file-descriptor syslog=off     [ lowerable deny count ]
process.max-core-size       syslog=off     [ lowerable deny no-signal bytes ]
process.max-stack-size      syslog=off     [ lowerable deny no-signal bytes ]
process.max-data-size       syslog=off     [ lowerable deny no-signal bytes ]
process.max-file-size       syslog=off     [ lowerable deny file-size bytes ]
process.max-cpu-time        syslog=off     [ lowerable no-deny cpu-time inf seconds ]
...

スタックサイズを「無制限」に設定しようとしましたが、顕著な違いはありませんでした。

# df
/                  (/dev/dsk/c1t0d0s0 ):86262876 blocks  7819495 files
/devices           (/devices          ):       0 blocks        0 files
/system/contract   (ctfs              ):       0 blocks 2147483608 files
/proc              (proc              ):       0 blocks    29937 files
/etc/mnttab        (mnttab            ):       0 blocks        0 files
/etc/svc/volatile  (swap              ):14661104 blocks  1180179 files
/system/object     (objfs             ):       0 blocks 2147483465 files
/etc/dfs/sharetab  (sharefs           ):       0 blocks 2147483646 files
/platform/sun4u-us3/lib/libc_psr.so.1(/platform/sun4u-us3/lib/libc_psr/libc_psr_hwcap1.so.1):86262876 blocks  7819495 files
/platform/sun4u-us3/lib/sparcv9/libc_psr.so.1(/platform/sun4u-us3/lib/sparcv9/libc_psr/libc_psr_hwcap1.so.1):86262876 blocks  7819495 files
/dev/fd            (fd                ):       0 blocks        0 files
/tmp               (swap              ):14661104 blocks  1180179 files
/var/run           (swap              ):14661104 blocks  1180179 files
/home              (/dev/dsk/c1t1d0s0 ):110125666 blocks  8388083 files

編集1:16 GBスワップファイルを設定した後の出力スワップ:

注:ブロックサイズは512です。

# swap -l
swapfile            dev    swaplo   blocks    free
/dev/dsk/c1t0d0s1   32,25  16       2106416   2106416  
/home/me/tmp/swapfile -    16       32964592  32964592

# swap -s
total: 172096k bytes allocated + 52576k reserved = 224672k used, 23875344k available 

ベストアンサー1

試してみるいくつかのことがあります。

  1. @AndrewHenle は正しいと思いますより多くのスワップスペースが必要です。
  2. -ftemplate-depthGCCのテンプレートとconstexpr再帰深度制限(およびconstexpr -fconstexpr-depth)を操作してみることができます。しかし、どんな表現がメモリ不足を引き起こすのかを理解するのに最大限に役立つことを願っています。
  3. いくつかのデバッグのヒント(詳細は以下を参照)

この資料では、Solaris でスワップ領域を増やす方法について詳しく説明します。しかし、いつかリンクが壊れるので、記事の概要は次のとおりです。

# Identify the current swap volume.
$ swap -l
swapfile                 dev  swaplo   blocks   free
/dev/zvol/dsk/rpool/swap 256,1      16 1058800 1058800
# Do one of the following:
# a) Modify the existing swap volume (REQUIRES REBOOT)
    $ zfs get volsize rpool/swap
    NAME        PROPERTY  VALUE    SOURCE
    rpool/swap  volsize   517M     -

    $ zfs set volsize=2g rpool/swap

    $ zfs get volsize rpool/swap
    NAME        PROPERTY  VALUE    SOURCE
    rpool/swap  volsize   2G       -

    $ init 6
# b) Add an additional swap volume
    # Create it
    $ zfs create -V 2G rpool/swap2

    # Activate it
    $ swap -a /dev/zvol/dsk/rpool/swap2

    $ swap -l
    swapfile                  dev  swaplo   blocks   free
    /dev/zvol/dsk/rpool/swap  256,1      16 1058800 1058800
    /dev/zvol/dsk/rpool/swap2 256,3      16 4194288 4194288

    # Add an entry for the new volume in /etc/vfstab
    $ /opt/csw/gnu/grep -P '\sswap' /etc/vfstab
    /dev/zvol/dsk/rpool/swap  - - swap - no -
    /dev/zvol/dsk/rpool/swap2 - - swap - no -

問題を診断するには、次のことを試すことができます。

# This tells Solaris to add all available sections into coredumps &
# place coredumps in your home directory with the given pattern
$ coreadm -p ~/%t.%n.%u.%f.%p.core -P all

$ gcc ${flags} source.cc -fsyntax-only
$ gcc ${flags} source.cc -c -o source.o

閲覧または試してみてください。

  • 衝突しますか-fsyntax-only
  • どちらもクラッシュすると、ほぼ同じコアダンプサイズが生成されますか?
  • コアダンプサイズは、競合が発生する前にプロセスによって取得されたメモリ量を示す必要があります。これをシステム制限と比較してみてください。
    • topSolarisシステムでは、物理メモリ511G、使用可能メモリ153G、合計スワップスペース20G、使用可能スワップスペース20Gを表示できます。
    • 実行swap -lと比較
  • スワップサイズを変更した後の動作に顕著な変化はありますか?
    • 衝突が早く発生し、衝突するのに時間がかかります。
    • コアサイズは多様
  • 意図的に小さいスワップサイズを使用するか、スワップパーティションを完全に削除して、より速くクラッシュするか、より小さなコアダンプを生成するか、または他の方法で動作が変更されることを確認してください。
  • 大きなハードドライブを挿入し、ドライブ全体を交換用に使用します。

また、次のようないくつかのGCCフラグを確認してください。

  • -Q各パスのコンパイル時関数名と統計を印刷します。
  • -ftime-report配送別時間情報
  • 様々な-fdump-rtl*
  • さまざまな手順(プリプロセッサ、アセンブリなど)から出力を取得して、他の動作が表示されることを確認してください。

おすすめ記事