Linux meldet die Prozessgröße beim Heap-Multimapping falsch

Linux meldet die Prozessgröße beim Heap-Multimapping falsch

Dieses Problem tritt unter Linux auf, wenn ein Prozess denselben physischen Speicher gleichzeitig mehreren Adressen zuordnet („Heap-Multi-Mapping“).

Zum Beispiel,Javas ZGC-Garbage Collectormacht dies.

Wenn Heap-Multimapping auftritt, berechnet Linux (zumindest die von mir verwendeten Versionen) die Größe des residenten Prozesses falsch (überhöht). Dies betrifft top und alle Programme, die das Betriebssystem nach Prozessgrößen abfragen.

Tatsächlich habe ich keine Möglichkeit mehr, zu erfahren, wie groß ein Prozess tatsächlich ist.

Dieser Screenshot zeigt ein ZGC-fähiges Java-Programm mit <<200 MB an Java-Objekten. In Wirklichkeit ist der Prozess also etwa 500 MB groß, nicht mehrere GB.

Bildbeschreibung hier eingeben

Kommen wir also zur Frage: Kennt jemand eine Linux-Version (oder einen Patch oder ein Tool), die in diesem Fall die Prozessgrößen korrekt melden kann?

Bearbeiten:Ich habe jetzt mein eigenes kleines Werkzeug gemachtspeziell für den ZGC-Anwendungsfall.

Antwort1

Sie können den Kernel fragen, wie der Prozess den Speicher nutzt ( /proc/PID/smaps) und dann die Berechnung auf Grundlage des gemeldeten gemeinsam genutzten und privaten Speichers durchführen. Der gemeinsam genutzte Speicher darf nur einmal gezählt werden.

Unten sehen Sie Code, der Smaps analysiert und die verschiedenen Arten der Speichernutzung für eine Liste von PIDs zusammenfasst. Der Unique Set Size (USS)-Speicher ist der private Speicher des Prozesses und könnte eine bessere Vorstellung davon vermitteln, wie viel Speicher der Prozess tatsächlich nutzt. Letztendlich ist es eine Frage, wie Sie den gemeinsam genutzten Speicher in die Gleichung einbeziehen möchten.

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

verwandte Informationen