Linux는 힙 다중 매핑으로 프로세스 크기를 잘못 보고합니다.

Linux는 힙 다중 매핑으로 프로세스 크기를 잘못 보고합니다.

프로세스가 동일한 물리적 메모리를 동시에 여러 주소에 매핑할 때("힙 다중 매핑") Linux에 이 문제가 있습니다.

예를 들어,Java의 ZGC 가비지 수집기이것을 한다.

힙 다중 매핑이 발생하면 Linux(적어도 내가 사용하는 버전)는 상주 프로세스 크기를 잘못 계산(과대보고)합니다. 이는 OS에서 프로세스 크기를 쿼리하는 상위 프로그램과 모든 프로그램에 영향을 미칩니다.

실제로 프로세스가 실제로 얼마나 큰지 더 이상 알 수 없습니다.

이 스크린샷은 Java 개체가 200MB 미만인 ZGC 지원 Java 프로그램에 대해 맨 위에 표시되는 것입니다. 따라서 실제로 프로세스는 몇 GB가 아닌 약 500MB입니다.

여기에 이미지 설명을 입력하세요

그렇다면 질문에 답해 보겠습니다. 이 경우 프로세스 크기를 올바르게 보고할 수 있는 Linux 버전(또는 패치 또는 도구)을 아는 사람이 있습니까?

편집하다:이제 나만의 작은 도구를 만들었어요특히 ZGC 사용 사례에 적합합니다.

답변1

프로세스가 메모리를 어떻게 사용하는지( ) 커널에 문의한 /proc/PID/smaps다음 보고된 공유 및 개인 메모리를 기반으로 계산을 수행할 수 있습니다. 공유 메모리는 한 번만 계산되어야 합니다.

다음은 smap을 구문 분석하고 pid 목록에 대한 다양한 유형의 메모리 사용량을 요약하는 일부 코드입니다. 고유한 세트 크기(uss) 메모리는 프로세스의 전용 메모리이며 프로세스가 실제로 사용하는 메모리 양에 대한 더 나은 아이디어를 제공할 수 있습니다. 궁극적으로 공유 메모리를 방정식에 어떻게 포함시키고 싶은지에 대한 질문이 됩니다.

rss = '.+?Rss:\s+(\d+)'
pss = '.+?Pss:\s+(\d+)'
shared_clean = '.+?Shared_Clean:\s+(\d+)'
shared_dirty = '.+?Shared_Dirty:\s+(\d+)'
priv_clean = '.+?Private_Clean:\s+(\d+)'
priv_dirty = '.+?Private_Dirty:\s+(\d+)'
MEM_REGEXP = /#{rss}#{pss}#{shared_clean}#{shared_dirty}#{priv_clean}#{priv_dirty}/m

def self.get_memory_map( pids)

    memory_map = {}
    #memory_map[ :pids_searched] = pids
    memory_map[ :pids_found] = {}
    memory_map[ :rss] = 0
    memory_map[ :pss] = 0
    memory_map[ :shared_clean] = 0
    memory_map[ :shared_dirty] = 0
    memory_map[ :rss_shared] = 0
    memory_map[ :priv_clean] = 0
    memory_map[ :priv_dirty] = 0
    memory_map[ :uss] = 0

    pids.each do |pid|
        begin
            # We don't want to see any "/proc/9723: No such file or directory" messages in stderr
            lines = nil
            Util.silently { lines = File.read( "/proc/#{pid}/smaps") }
        rescue
            lines = nil
        end
        if lines
            lines.scan(MEM_REGEXP) do |rss,pss,shared_clean,shared_dirty,priv_clean,priv_dirty|
                memory_map[ :pids_found][pid] = true
                memory_map[ :rss] += rss.to_i
                memory_map[ :pss] += pss.to_i
                memory_map[ :shared_clean] += shared_clean.to_i
                memory_map[ :shared_dirty] += shared_dirty.to_i
                memory_map[ :rss_shared] += shared_clean.to_i + shared_dirty.to_i
                memory_map[ :priv_clean] += priv_clean.to_i
                memory_map[ :priv_dirty] += priv_dirty.to_i
                memory_map[ :uss] += priv_clean.to_i + priv_dirty.to_i
            end
        end
    end
    memory_map[ :pids_found] = memory_map[ :pids_found].keys
    return memory_map
end

관련 정보