我们如何计算进程对“提交”的贡献(/proc/meminfo“Committed_AS”)

我们如何计算进程对“提交”的贡献(/proc/meminfo“Committed_AS”)

我们发现“提交”随着时间的推移出现了“泄漏”,需要跟踪有问题的进程。RSS(“已用”内存”)没有泄漏,但提交有泄漏,这导致内核行为非常糟糕(当提交百分比达到 ~ 200% 时无法分配内存)。我知道我们可以使用 /proc/sys/vm/overcommit_memory 来调整它,但这不是重点 - 我们想找到泄漏的进程。

我已尝试从 etc/(proc)/smap 和 dmap 进行各种计算,但是所有进程中没有任何内容与 /proc/meminfo 中的提交类似。 https://www.kernel.org/doc/Documentation/vm/overcommit-accounting非常模糊,我不清楚如何使用它。

有什么建议么?

答案1

发布内容是为了提供我们如何解决这个问题 - 并不优雅或精致,也不是直接的答案(我们没有获得进程的实际过度提交分配),但我们确定了罪魁祸首并发现了一个微妙的内存泄漏。

对于没有评论等,请多多包涵,但这些都是快速使用的工具。有了它...

我们查看了pmap命令结果和进程数据扫描/etc/<pid>/smaps,汇总了同一进程的副本,然后将其加载到电子表格中进行分析。我们在一周内每天拍摄几次快照,并查看了内存使用趋势。这向我们展示了具有相同名称的一组进程的内存随时间变化的趋势,这使我们能够识别有问题的进程集。

控制脚本(运行一组命令并将结果组织在一个文件中)

gpmemstatFile=gpmemstat.$(日期“+%F.%H.%M.%S.%N”| cut -c 1-23)
echo '--------------------------------------------------------' >> $gpmemstatFile
echo $(主机名) >> $gpmemstatFile
echo $(日期) >> $gpmemstatFile
echo '--------------------------------------------------------' >> $gpmemstatFile
echo >> $gpmemstatFile

echo '--------------------------------------------------------' >> $gpmemstatFile
echo ‘/proc/meminfo’ >> $gpmemstatFile
echo '--------------------------------------------------------' >> $gpmemstatFile
cat /proc/meminfo >> $gpmemstatFile
echo >> $gpmemstatFile

echo '--------------------------------------------------------' >> $gpmemstatFile
回显‘sar -r’>>$gpmemstatFile
echo '--------------------------------------------------------' >> $gpmemstatFile
sar -r >> $gpmemstat文件
echo >> $gpmemstatFile

echo '--------------------------------------------------------' >> $gpmemstatFile
回显‘sar -R’>>$gpmemstatFile
echo '--------------------------------------------------------' >> $gpmemstatFile
sar -R >> $gpmemstat文件
echo >> $gpmemstatFile

echo '--------------------------------------------------------' >> $gpmemstatFile
echo ‘gpsmapstat (/proc/(pid)/smaps 聚合)’ >> $gpmemstatFile
echo '--------------------------------------------------------' >> $gpmemstatFile
gpsmapsstat httpd oninit fglrun java fastcgi gdcproxy >> $gpmemstatFile
echo >> $gpmemstatFile

echo '--------------------------------------------------------' >> $gpmemstatFile
echo ‘gppmapstat (pmap -d -x 聚合)’ >> $gpmemstatFile
echo '--------------------------------------------------------' >> $gpmemstatFile
gppmapstat httpd oninit fglrun java fastcgi gdcproxy >> $gpmemstatFile

如果 [ -n "$1" ]; 那么
   scp $gpmemstat文件$1

该脚本用于收集pmap特定名称的所有进程的进程数据(您可以使用其他机制来识别要分析的进程)。它汇总了某一类型的所有进程的总内存使用量。


printf "%8s %8s %8s %8s %8s %8s %8s %8s\n" name PID Total  Resident Dirty Private Shared Unshared
for name in $@  ; do

    unset sumTotalMemory sumResidentMemory sumDirtyMemory sumPrivateMemory sumSharedMemory sumUnsharedMemory 


    for pid in $( ps aux | grep $name | awk  '{print $2}') ; do
        xMemory=$(pmap -x $pid | tail -1)
        totalMemory=$(echo $xMemory | awk '{print $3}')
        if [ -n "$totalMemory" ] ; then sumTotalMemory=$(($sumTotalMemory + $totalMemory)) ; fi
        residentMemory=$(echo $xMemory | awk '{print $4}')
        if [ -n "$residentMemory" ] ; then sumResidentMemory=$(($sumResidentMemory + $residentMemory)) ; fi
        dirtyMemory=$(echo $xMemory | awk '{print $5}')
        if [ -n "$dirtyMemory" ] ; then sumDirtyMemory=$(($sumDirtyMemory + $dirtyMemory)) ; fi

        dMemory=$(pmap -d $pid | tail -1)
        privateMemory=$(echo $dMemory | awk '{print $4}')
        if [ -n "$privateMemory" ] ; then 
            privateMemory=${privateMemory:0:${#privateMemory}-1}
            sumPrivateMemory=$(($sumPrivateMemory + $privateMemory))
        fi
        sharedMemory=$(echo $dMemory | awk '{print $6}')
        unset unsharedMemory
        if [ -n "$sharedMemory" ] ; then 
            sharedMemory=${sharedMemory:0:${#sharedMemory}-1} 
            sumSharedMemory=$(($sumSharedMemory + $sharedMemory ))
            unsharedMemory=$(($totalMemory - $sharedMemory))
            sumUnsharedMemory=$(( $sumUnsharedMemory + $unsharedMemory ))
        fi

        #printf "%8s %8s %8s %8s %8s %8s %8s %8s\n" $name $pid $totalMemory $residentMemory $dirtyMemory $privateMemory $sharedMemory $unsharedMemory

    done

    if [ -n "$sumTotalMemory" ] ; then
        printf "%8s %8s %8s %8s %8s %8s %8s %8s\n" $name Total $sumTotalMemory $sumResidentMemory $sumDirtyMemory $sumPrivateMemory $sumSharedMemory $sumUnsharedMemory
        printf "%8s %8s %8s %8s %8s %8s %8s %8s\n" $name MiB $(($sumTotalMemory/1024)) $(($sumResidentMemory/1024)) $(($sumDirtyMemory/1024)) $(($sumPrivateMemory/1024)) $(($sumSharedMemory/1024)) $(($sumUnsharedMemory/1024))
        printf "%8s %8s %8s %8s %8s %8s %8s %8s\n" $name GiB $(echo "scale=2; $sumTotalMemory/1024/1024" | bc) $(echo "scale=2; $sumResidentMemory/1024/1024" | bc) $(echo "scale=2; $sumDirtyMemory/1024/1024" | bc)  $(echo "scale=2; $sumPrivateMemory/1024/1024"| bc) $(echo "scale=2; $sumSharedMemory/1024/1024"| bc) $(echo "scale=2; $sumUnsharedMemory/1024/1024"| bc)
    fi
done

该脚本查看所有proc/<pid>/smaps文件,并汇总特定名称的所有进程的内存数据(同样,您可以使用其他机制来识别要分析的进程)。这再次总结了某一类型的所有进程的内存使用总量。


printf "%8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n" name size rss pss shrdCln shrdDrty prvtCln prvtDrty refrncd swap
for name in $*; do

    unset awkFiles
    for pid in $( ps aux | grep $name | awk  '{print $2}') ; do
        if [ -e /proc/$pid/smaps ] ; then   
            awkFiles=${awkFiles}" /proc/$pid/smaps"
        fi
    done
    if [ -n "$awkFiles" ] ; then
        awk -v name="$name" '{ 
            if ($1 == "Size:" ){
                sizeSum+=$2
            }
            else if ($1 == "Rss:" ){
                rssSum+=$2
            }
            else if ($1 == "Pss:" ){
                pssSum+=$2
            }
            else if ($1 == "Shared_Clean:" ){
                sharedCleanSum+=$2
            }
            else if ($1 == "Shared_Dirty:" ){
                sharedDirtySum+=$2
            }
            else if ($1 == "Private_Clean:" ){
                privateCleanSum+=$2
            }
            else if ($1 == "Private_Dirty:" ){
                privateDirtySum+=$2
            }
            else if ($1 == "Referenced:" ){
                referencedSum+=$2
            }
            else if ($1 == "Swap:" ){
                swapSum+=$2
            }
        }  
        END { printf "%8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n", name, sizeSum, rssSum, pssSum, sharedCleanSum, sharedDirtySum, privateCleanSum, privateDirtySum, referencedSum, swapSum}' $awkFiles
    fi
done

再次,并不完善,也不是实际的答案(我仍然不知道如何获取内存提交电荷排序列表中的进程),但它在这里确实起了作用。

答案2

我不确定我是否正确理解了你的问题,但首先我想找出实际内存使用情况以及实际共享内存。请使用下面提到的 python 脚本

             https://raw.githubusercontent.com/pixelb/ps_mem/master/ps_mem.py

希望这会有所帮助或迈出调试的第一步......

相关内容