私たちのチームはすべて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
試してみるいくつかのことがあります。
- @AndrewHenle は正しいと思いますより多くのスワップスペースが必要です。。
-ftemplate-depth
GCCのテンプレートとconstexpr再帰深度制限(およびconstexpr-fconstexpr-depth
)を操作してみることができます。しかし、どんな表現がメモリ不足を引き起こすのかを理解するのに最大限に役立つことを願っています。- いくつかのデバッグのヒント(詳細は以下を参照)
この資料では、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
? - どちらもクラッシュすると、ほぼ同じコアダンプサイズが生成されますか?
- コアダンプサイズは、競合が発生する前にプロセスによって取得されたメモリ量を示す必要があります。これをシステム制限と比較してみてください。
top
Solarisシステムでは、物理メモリ511G、使用可能メモリ153G、合計スワップスペース20G、使用可能スワップスペース20Gを表示できます。- 実行
swap -l
と比較
- スワップサイズを変更した後の動作に顕著な変化はありますか?
- 衝突が早く発生し、衝突するのに時間がかかります。
- コアサイズは多様
- 意図的に小さいスワップサイズを使用するか、スワップパーティションを完全に削除して、より速くクラッシュするか、より小さなコアダンプを生成するか、または他の方法で動作が変更されることを確認してください。
- 大きなハードドライブを挿入し、ドライブ全体を交換用に使用します。
また、次のようないくつかのGCCフラグを確認してください。
-Q
各パスのコンパイル時関数名と統計を印刷します。-ftime-report
配送別時間情報- 様々な
-fdump-rtl*
旗 - さまざまな手順(プリプロセッサ、アセンブリなど)から出力を取得して、他の動作が表示されることを確認してください。
答え2
これはgmake 3.81のバグであることがわかりました。 makeを使用せずに直接コンパイルコマンドを実行すると、より多くのメモリを使用できます。 3.80には既知のバグがあるようです。このような。このバグは3.81で修正する必要があります。しかし、非常に似たエラーが発生しました。
だからgmake 3.82を使ってみました。コンパイルが続行され、VM エラーは表示されなくなります。
私はコアをダンプできなかったので、実際には仮想メモリ、gmake、g ++、またはasが不足していることを知りません。そのエラーに対してコアをダンプしません。このバグが正確に何であるかはわかりませんが、現在は動作しているようです。