Linux オペレーティングシステムが長時間稼働すると、メモリの断片化が発生することがあります。 このトピックでは、この問題に対するソリューションを説明します。
問題の説明
インスタンスにデプロイされたサービスで、応答時間やシステムコールの時間が長くなることがあります。 このような場合、システムの sys メトリックが増加し、バディシステムに高次メモリ (order が 3 より大きいメモリ) が不足します。 たとえば、cat /proc/buddyinfo コマンドを実行すると、次のような出力が返されます。 4 列目以降は、バディシステム内の異なる order の空きメモリを表します。
cat /proc/buddyinfo
Node 0, zone DMA 1 0 0 1 2 1 1 0 1 1 3
Node 0, zone DMA32 3173 856 529 0 0 0 0 0 0 0 0
Node 0, zone Normal 19030 8688 7823 0 0 0 0 0 0 0 0考えられる原因
Linux システムが長時間稼働すると、大きな隣接した物理メモリブロックがより小さなブロックに分割されます。 システムにデプロイされたサービスが大きな隣接メモリブロックをリクエストすると、システムは時間のかかるメモリコンパクションプロセスを開始します。 これにより、パフォーマンスの変動が発生する可能性があります。 メモリの断片化が発生した場合、カーネルスタック情報は通常、次の例のようになります。
0xffffffff8118f9cb compaction_alloc ([kernel.kallsyms])
0xffffffff811c88a9 migrate_pages ([kernel.kallsyms])
0xffffffff811901ee compact_zone ([kernel.kallsyms])
0xffffffff8119041b compact_zone_order ([kernel.kallsyms])
0xffffffff81190735 try_to_compact_pages ([kernel.kallsyms])
0xffffffff81631cb4 __alloc_pages_direct_compact ([kernel.kallsyms])
0xffffffff811741d5 __alloc_pages_nodemask ([kernel.kallsyms])
0xffffffff811b5a79 alloc_pages_current ([kernel.kallsyms])
0xffffffff811c0005 new_slab ([kernel.kallsyms])
0xffffffff81633848 __slab_alloc ([kernel.kallsyms])
0xffffffff811c5291 __kmalloc_node_track_caller ([kernel.kallsyms])
0xffffffff8151a8c1 __kmalloc_reserve.isra.30 ([kernel.kallsyms])
0xffffffff8151b7cd alloc_sib ([kernel.kallsyms])
0xffffffff815779e9 sk_stream_alloc_skb ([kernel.kallsyms])
0xffffffff8157872d tcp_sendmsg ([kernel.kallsyms])
0xffffffff815a26b4 inet_sendmsg ([kernel.kallsyms])
0xffffffff81511017 sock_aio_write ([kernel.kallsyms])
0xffffffff811df729 do_sync_readv_writev ([kernel.kallsyms])
0xffffffff811e0cfe do_readv_writev ([kernel.kallsyms])ソリューション
Linux のメモリの断片化に対処するために、以下の対策を講じることができます:
最小ウォーターマークの調整
最小ウォーターマークを総メモリの 1% から 3% に設定できます。 2% の値が推奨されます。 これにより、メモリリソースが少ない場合に、非同期の再利用が早期にトリガーされます。 次のコマンドを実行して、最小ウォーターマークを調整します:
sysctl -w vm.min_free_kbytes = memtotal_kbytes * 2%このコマンドの memtotal_kbytes * 2% 変数は、インスタンスの総メモリの 2% を表します。
最小ウォーターマークと低ウォーターマークの差分の調整
watermark_scale_factorカーネルパラメーターを使用して、最小ウォーターマークと低ウォーターマークの差分を調整できます。 これにより、サービスからの突然のメモリリクエストを管理できます。watermark_scale_factorのデフォルト値は、総メモリの 0.1% です。 最小値、つまり最小ウォーターマークと低ウォーターマークの間の最小の差分は、0.5*min watermarkです。 次のコマンドを実行してwatermark_scale_factorを調整します:sysctl -w vm.watermark_scale_factor = valueこのコマンドの value 変数は、最小ウォーターマークと低ウォーターマークの間に設定した差分です。
定期的なメモリコンパクションの実行
オフピーク時に、手動で非同期メモリコンパクションをトリガーできます。 次のコマンドを実行してプロセスをトリガーします:
echo 1 > /proc/sys/vm/compact_memory定期的なキャッシュの手動解放
上記までの対策でメモリの断片化が解決しない場合は、オフピーク時にキャッシュを解放 (
drop cache) することもできます。 その後、メモリは再割り当てされます。 キャッシュの解放は、メモリの断片化を防ぐ効果的な方法です。 ただし、この操作により、システムのパフォーマンスが一時的に変動する可能性があります。 次のコマンドを実行して、手動でキャッシュを解放します:echo 3 > /proc/sys/vm/drop_caches