2017-11-20 2 views
2

Ich versuche herauszufinden, wie viel RAM von einer Karte verbraucht wird. Also, ich habe folgendes; -Java Memory Used

Map<String,Double> cr = crPair.collectAsMap(); // 200+ entries 
System.out.println("free memory = " + Runtime.getRuntime().freeMemory()); 
Map<String,Double> gen = new HashMap<>(); 
gen.putAll(cr); 
System.out.println("free memory = " + Runtime.getRuntime().freeMemory()); 

Die Antwort, die ich bekam, war: -

free memory = 940714880 
free memory = 940714880 

Ich wollte im Grunde, um zu sehen, wie viele Einträge meine Karte vor Überschreiten einer bestimmten Schwelle unterstützen. Dies impliziert jedoch keine zusätzlichen Bytes. Was vermisse ich? Kann jemand auch eine grobe Schätzung geben, wie viel Platz von einer Hashmap eingenommen wird (Reihenfolge von 1000 Einträgen).

+0

http://java-performance.info/memory-consumption-of- Java-Datentypen-2 / – Rjiuk

Antwort

2

Runtime.freeMemory gibt nur eine grobe Schätzung zurück. Es eignet sich nicht zum Messen von Speicher, der von einem bestimmten Objekt belegt ist.

Sie können JMH mit eingebautem -prof gc Profiler verwenden, um eine viel genauere Schätzung zu erhalten. Hier ist ein Beispiel-Benchmark, um den von einer HashMap belegten Speicherplatz zu messen (ohne den Speicher, der von Schlüsseln und Werten selbst verwendet wird).

package bench; 

import org.openjdk.jmh.annotations.*; 

import java.util.HashMap; 
import java.util.Map; 
import java.util.concurrent.ThreadLocalRandom; 
import java.util.stream.Collectors; 
import java.util.stream.IntStream; 

@State(Scope.Benchmark) 
public class MapSizeBench { 
    @Param({"10", "100", "1000", "10000", "100000"}) 
    int size; 

    Map<String, Double> map; 

    @Setup 
    public void setup() { 
     map = IntStream.range(0, size).boxed().collect(Collectors.toMap(
       n -> "key" + n, 
       n -> ThreadLocalRandom.current().nextDouble())); 
    } 

    @Benchmark 
    public Map<String, Double> hashMap() { 
     return new HashMap<>(map); 
    } 
} 

gc.alloc.rate.norm Wert die Anzahl von Bytes zugewiesen zeigen, während das Verfahren mit @Benchmark Annotation gekennzeichnet ausführt:

Benchmark         (size) Mode Cnt  Score Error Units 
MapSizeBench.hashMap:·gc.alloc.rate.norm  10 avgt 5  448,000 ± 0,001 B/op 
MapSizeBench.hashMap:·gc.alloc.rate.norm  100 avgt 5  4288,001 ± 0,001 B/op 
MapSizeBench.hashMap:·gc.alloc.rate.norm  1000 avgt 5 40256,009 ± 0,002 B/op 
MapSizeBench.hashMap:·gc.alloc.rate.norm 10000 avgt 5 385640,093 ± 0,017 B/op 
MapSizeBench.hashMap:·gc.alloc.rate.norm 100000 avgt 5 4248681,606 ± 0,329 B/op 

Das heißt, ein HashMap von 1000 Elementen nimmt ungefähr 40 KB auf JDK 8 x64 mit CompressedOops aktiviert.

Alternativ können Sie die volle Heapdump nehmen:

jmap -dump:format=b,file=heap.hprof <pid> 

und analysieren es in Eclipse Memory Analyzer. Dieses Tool kann Ihnen den Speicher zeigen, der von einem bestimmten Objekt oder einem Objektgraphen belegt ist.

2

Zuerst gibt es ein spezielles Werkzeug zum Messen dieser Dinge JOL genannt.

mit Spielen ist ganz einfach und es wird Ihnen einige sehr gute Eingabe, zum Beispiel:

HashMap<String, String> map = new HashMap<>(8); 
map.put("key", "value"); 

for (int i = 0; i < 2_000; i++) { 
    map.put("key" + i, "value"); 
} 

System.out.println(GraphLayout.parseInstance(map).totalSize()); 

Auch this answer is very much related