SlideShare a Scribd company logo
1
● Jan Kotek
– jan@kotek.net
– @JanKotek
– MapDB author (database engine)
– Java developer for past 12 years
– Last 3 years independent consultant for MapDB
● Slides and code at
– https://github.com/jankotek/talk-save-java-memory
Intro
2
Intro
● This talk is about:
– Reducing memory footprint
– Object overhead
– Primitive variables and arrays
– Alternative Java Collections
● Not about:
– Garbage Collection
– Off-heap
– Performance
– Memory leaks
3
Measure memory consumption
● Runtime.getRuntime().freeMemory() difference
● Allocate until OutOfMemoryError
● Profiler
● Class or heap dump analyze such as Java Object Layout
4
Runtime.getRuntime().freeMemory()
● Get allocated memory stats
● Create new objects
● Call GC many times
● Get allocated memory difference
● Not very precise, but easy
● May not always work,
some JVMs ignore System.gc()
NanoBench nanoBench = NanoBench.create();
nanoBench.memoryOnly().warmUps(2).measurements(10)
.measure(String.format("Measure memory for %d keys", i),
new Runnable() {
@Override public void run() {
Random setRandom = new Random(4532);
ref = new HashSet<Integer>(cnt);
w hile (ref.size() < cnt) {
ref.add(setRandom.nextInt());
}
}
});
nanoBench.getMemoryBytes()
5
OutOfMemoryError
● Memory limit (-Xmx1G)
● Add entries to array in loop
● Print number of items
● JVM eventually crashes
try{
//add new entry in loop
while(true)
array[arrayPos++] = new HashMap();
}catch(OutOfMemoryError e){
memoryConsumption =
Runtime.getRuntime().maxMemory()
/ counter;
return;
}
6
Profiler
● Shows memory consumed
by single class
– (byte[], Object[])
● VisualVM is easy to use
● Flight Recorder is best
– Free outside production env.
7
Java Object Layout
● Command line tool to analyze memory layout (and space usage)
● Most advanced
● http://openjdk.java.net/projects/code-tools/jol/
● Written by Aleksey Shipilev
● Example:
$ java -jar jol-cli/target/jol-cli.jar internals java.util.HashMap
Instance size: 48 bytes (reported by Instrumentation API)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
8
Instance overhead in Java
● Pointer overhead
– 4 to 8 bytes
– depends on JVM and amount of memory
– 64bit JVM 8 uses compressed pointer when possible
● Class info and object header
– 12 bytes
● Object alligment padding
– Between 0 and 15
35 bytes worst case scenario
9
java.lang.Integer overhead
● One object + one reference
● Total overhead 16 bytes +
reference (4 to 8 bytes)
JOL output for java.lang.Integer
OFFSET SIZE TYPE DESC
0 12 (object header)
12 4 int Integer.value
total size: 16 bytes
10
java.lang.String overhead
● Two objects and two references
● One int field (String.hash)
● Two bytes per char (UTF16)
● Other problems:
– Weak hash (many collisions)
– Defensive char[] copies
– Substring create copies etc..
JOL output for java.lang.String
OFFSET SIZE TYPE DESC
0 4 (object header)
4 4 (object header)
8 4 (object header)
12 4 char[] String.value
16 4 int String.hash
20 4 (alignment loss)
total size: 24 bytes
11
String.intern()
●
Reduces number of instances
● Each string creates new weak ref (huge GC overhead)
● Long.valueOf(11) is similar
name.toLowerCase().intern()
==
name.toLowerCase().intern()
12
Represent String as char[]
● Field is char[] or byte[]
● Get/set takes string
● GC overhead, but short lived
objects are fast to collect
● Reduced memory with many
objects (large Maps etc)
public class Person{
private char[] name;
public String getName(){
return new String(name);
}
public void setName(String name){
this.name = name.toCharArray();
}
}
13
char[] as key in Map
● char[] has no equals() and hashCode() methods
●
TreeMap key can use Comparator<char[]>
– com.google.common.primitives.Chars.lexicographicalComparator()
● java.util.HashMap can not change hash strategy
– Object2ObjectOpenCustomHashMap from FastUtil has Hash Strategies
– String.hashCode() is broken, many collisions
● Part of spec, can not be changed :-(
● ConcurrentHashMap Java8 has sorted lists to handle hash duplicates :-)
14
char[] as value in Map
● Works (mostly)
● Concurrent Compare-And-Swap operations broken
– char[].equals() uses identity
– ConcurrentMap.replace(K key, V oldValue, V newValue);
– MapDB Maps allow custom equality
15
Bitwise
class Address{
String street;
int houseNumber;
}
● Replace street with number from dictionary
●
Combine streetId and houseNumber into single long number
– 5 bytes for streetId, 3 bytes for house number and flags
● Adress become primitive number, no objects or references
16
Primitive key / value in collections
● HashMap<Long,Long> uses Object[] for keys and values
● ~40 bytes overhead for each key-value pair
● Use long[] or int[] instead
● Data locality → CPU cache friendly
– Binary search much faster
– Faster fetch of values
● Almost zero Garbage Collection
– entire HashMap uses two objects
– No objects allocated for new key or value
17
FastUtil
● http://fastutil.di.unimi.it/
● Autogenerated classes with
primitive keys and values
● Int2IntMap, Int2BooleanMap, Int2ObjectMap<V> ….
● Many classes, 17MB jar
18
FastUtil
// create new map
Int2ObjectMap<String> map =
new Int2ObjectOpenHashMap();
// put/get has primitive arg, no unboxing!
map.put(1, "aa");
map.get(1);
// also implements full mapdb interface
Map<Integer, String> map2 = map;
● Parallel interface hierarchy
● Get / set has primitive arg
version, no unboxing!
● Implements Map interface
19
Chronicle Map
● ConcurrentHashMap
● Keys and values are serialized
outside heap
● Supports any serializable data
type
● No objects or references on
heap, memory efficient
● http://chronicle.software/product
s/chronicle-map/
Map<Long, long[]> graph =
ChronicleMap
.of(Long.class, long[].class)
.entries(1_000_000_000L)
.averageValue(new long[150])
.create();
20
Conclusion
● Avoid too many object instances in long lived objects
● Short lived objects are fine, when traded for smaller memory
● Email: jan@kotek.net
● Slides and code at
– https://github.com/jankotek/talk-save-java-memory

More Related Content

PDF
MapDB - taking Java collections to the next level
PPTX
PDF
Apache Tajo on Swift: Bringing SQL to the OpenStack World
PDF
Caching in (DevoxxUK 2013)
PDF
hadoop
PDF
Machine learning at Scale with Apache Spark
PDF
OQGraph at MySQL Users Conference 2011
PDF
Large volume data analysis on the Typesafe Reactive Platform
MapDB - taking Java collections to the next level
Apache Tajo on Swift: Bringing SQL to the OpenStack World
Caching in (DevoxxUK 2013)
hadoop
Machine learning at Scale with Apache Spark
OQGraph at MySQL Users Conference 2011
Large volume data analysis on the Typesafe Reactive Platform

What's hot (20)

PDF
Efficient Data Storage for Analytics with Apache Parquet 2.0
PPTX
Hadoop MapReduce framework - Module 3
PPTX
Introduction to MapReduce and Hadoop
PDF
Efficient Data Storage for Analytics with Parquet 2.0 - Hadoop Summit 2014
PDF
Precog & MongoDB User Group: Skyrocket Your Analytics
PDF
GBM in H2O with Cliff Click: H2O API
PDF
On Beyond (PostgreSQL) Data Types
PPT
BDAS Shark study report 03 v1.1
PPTX
Benefits of Using MongoDB Over RDBMS (At An Evening with MongoDB Minneapolis ...
PDF
Mapreduce Algorithms
PPTX
Modern software design in Big data era
PDF
Optimization Techniques
PPTX
MATLAB, netCDF, and OPeNDAP
PDF
How to use Parquet as a basis for ETL and analytics
PDF
Js info vis_toolkit
PDF
IOT with PostgreSQL
 
PDF
Introduction to Hadoop and MapReduce
PDF
Cliff Click Explains GBM at Netflix October 10 2013
PPTX
Fosdem2017 Scientific computing on Jruby
PDF
Map reduce: beyond word count
Efficient Data Storage for Analytics with Apache Parquet 2.0
Hadoop MapReduce framework - Module 3
Introduction to MapReduce and Hadoop
Efficient Data Storage for Analytics with Parquet 2.0 - Hadoop Summit 2014
Precog & MongoDB User Group: Skyrocket Your Analytics
GBM in H2O with Cliff Click: H2O API
On Beyond (PostgreSQL) Data Types
BDAS Shark study report 03 v1.1
Benefits of Using MongoDB Over RDBMS (At An Evening with MongoDB Minneapolis ...
Mapreduce Algorithms
Modern software design in Big data era
Optimization Techniques
MATLAB, netCDF, and OPeNDAP
How to use Parquet as a basis for ETL and analytics
Js info vis_toolkit
IOT with PostgreSQL
 
Introduction to Hadoop and MapReduce
Cliff Click Explains GBM at Netflix October 10 2013
Fosdem2017 Scientific computing on Jruby
Map reduce: beyond word count
Ad

Similar to Save Java memory (20)

PDF
JavaOne 2013: Memory Efficient Java
PDF
Java Memory Analysis: Problems and Solutions
PDF
Memory efficient java tutorial practices and challenges
PDF
Inside the JVM - Follow the white rabbit!
PDF
Out ofmemoryerror what is the cost of java objects
PDF
5 Coding Hacks to Reduce GC Overhead
PPTX
PDF
Faster persistent data structures through hashing
PPT
Memory efficient programming
ODP
From Java Code to Java Heap: Understanding the Memory Usage of Your App - Ch...
PDF
Inside the JVM - Follow the white rabbit! / Breizh JUG
PPTX
Java Performance Tips (So Code Camp San Diego 2014)
PDF
Java Performance Tuning
PPTX
Java Hands-On Workshop
PDF
Java collections the force awakens
PDF
Collections forceawakens
ODP
Best practices in Java
PDF
Faster persistent data structures through hashing
PDF
Cache is King ( Or How To Stop Worrying And Start Caching in Java) at Chicago...
PDF
Lecture notesmap
JavaOne 2013: Memory Efficient Java
Java Memory Analysis: Problems and Solutions
Memory efficient java tutorial practices and challenges
Inside the JVM - Follow the white rabbit!
Out ofmemoryerror what is the cost of java objects
5 Coding Hacks to Reduce GC Overhead
Faster persistent data structures through hashing
Memory efficient programming
From Java Code to Java Heap: Understanding the Memory Usage of Your App - Ch...
Inside the JVM - Follow the white rabbit! / Breizh JUG
Java Performance Tips (So Code Camp San Diego 2014)
Java Performance Tuning
Java Hands-On Workshop
Java collections the force awakens
Collections forceawakens
Best practices in Java
Faster persistent data structures through hashing
Cache is King ( Or How To Stop Worrying And Start Caching in Java) at Chicago...
Lecture notesmap
Ad

More from JavaDayUA (20)

PDF
STEMing Kids: One workshop at a time
PDF
Flavors of Concurrency in Java
PDF
What to expect from Java 9
PDF
Continuously building, releasing and deploying software: The Revenge of the M...
PDF
The Epic Groovy Puzzlers S02: The Revenge of the Parentheses
PDF
20 Years of Java
PDF
How to get the most out of code reviews
PDF
Unlocking the Magic of Monads with Java 8
PDF
Virtual Private Cloud with container technologies for DevOps
PPTX
JShell: An Interactive Shell for the Java Platform
PPTX
Interactive Java Support to your tool -- The JShell API and Architecture
PDF
Design rationales in the JRockit JVM
PPTX
Next-gen DevOps engineering with Docker and Kubernetes by Antons Kranga
PPTX
Apache Cassandra. Inception - all you need to know by Mikhail Dubkov
PPTX
Solution Architecture tips & tricks by Roman Shramkov
PPTX
Testing in Legacy: from Rags to Riches by Taras Slipets
PDF
Reactive programming and Hystrix fault tolerance by Max Myslyvtsev
PDF
Spark-driven audience counting by Boris Trofimov
PDF
API first with Swagger and Scala by Slava Schmidt
PPTX
JavaFX 8 everywhere; write once run anywhere by Mohamed Taman
STEMing Kids: One workshop at a time
Flavors of Concurrency in Java
What to expect from Java 9
Continuously building, releasing and deploying software: The Revenge of the M...
The Epic Groovy Puzzlers S02: The Revenge of the Parentheses
20 Years of Java
How to get the most out of code reviews
Unlocking the Magic of Monads with Java 8
Virtual Private Cloud with container technologies for DevOps
JShell: An Interactive Shell for the Java Platform
Interactive Java Support to your tool -- The JShell API and Architecture
Design rationales in the JRockit JVM
Next-gen DevOps engineering with Docker and Kubernetes by Antons Kranga
Apache Cassandra. Inception - all you need to know by Mikhail Dubkov
Solution Architecture tips & tricks by Roman Shramkov
Testing in Legacy: from Rags to Riches by Taras Slipets
Reactive programming and Hystrix fault tolerance by Max Myslyvtsev
Spark-driven audience counting by Boris Trofimov
API first with Swagger and Scala by Slava Schmidt
JavaFX 8 everywhere; write once run anywhere by Mohamed Taman

Recently uploaded (20)

DOCX
The Future of Smart Factories Why Embedded Analytics Leads the Way
PPTX
Save Business Costs with CRM Software for Insurance Agents
PPTX
What to Capture When It Breaks: 16 Artifacts That Reveal Root Causes
PDF
Convert Thunderbird to Outlook into bulk
PDF
The Role of Automation and AI in EHS Management for Data Centers.pdf
PPTX
Benefits of DCCM for Genesys Contact Center
PDF
Jenkins: An open-source automation server powering CI/CD Automation
PPTX
Maximizing Revenue with Marketo Measure: A Deep Dive into Multi-Touch Attribu...
PDF
Emergency Mustering solutions – A Brief overview
PDF
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
PDF
How Creative Agencies Leverage Project Management Software.pdf
PPTX
Presentation of Computer CLASS 2 .pptx
PPTX
AIRLINE PRICE API | FLIGHT API COST |
PDF
Community & News Update Q2 Meet Up 2025
PDF
Build Multi-agent using Agent Development Kit
PDF
Micromaid: A simple Mermaid-like chart generator for Pharo
PDF
QAware_Mario-Leander_Reimer_Architecting and Building a K8s-based AI Platform...
PDF
The Future of Smart Factories Why Embedded Analytics Leads the Way
PDF
How to Confidently Manage Project Budgets
PDF
A Practical Breakdown of Automation in Project Management
The Future of Smart Factories Why Embedded Analytics Leads the Way
Save Business Costs with CRM Software for Insurance Agents
What to Capture When It Breaks: 16 Artifacts That Reveal Root Causes
Convert Thunderbird to Outlook into bulk
The Role of Automation and AI in EHS Management for Data Centers.pdf
Benefits of DCCM for Genesys Contact Center
Jenkins: An open-source automation server powering CI/CD Automation
Maximizing Revenue with Marketo Measure: A Deep Dive into Multi-Touch Attribu...
Emergency Mustering solutions – A Brief overview
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
How Creative Agencies Leverage Project Management Software.pdf
Presentation of Computer CLASS 2 .pptx
AIRLINE PRICE API | FLIGHT API COST |
Community & News Update Q2 Meet Up 2025
Build Multi-agent using Agent Development Kit
Micromaid: A simple Mermaid-like chart generator for Pharo
QAware_Mario-Leander_Reimer_Architecting and Building a K8s-based AI Platform...
The Future of Smart Factories Why Embedded Analytics Leads the Way
How to Confidently Manage Project Budgets
A Practical Breakdown of Automation in Project Management

Save Java memory

  • 1. 1 ● Jan Kotek – [email protected] – @JanKotek – MapDB author (database engine) – Java developer for past 12 years – Last 3 years independent consultant for MapDB ● Slides and code at – https://github.com/jankotek/talk-save-java-memory Intro
  • 2. 2 Intro ● This talk is about: – Reducing memory footprint – Object overhead – Primitive variables and arrays – Alternative Java Collections ● Not about: – Garbage Collection – Off-heap – Performance – Memory leaks
  • 3. 3 Measure memory consumption ● Runtime.getRuntime().freeMemory() difference ● Allocate until OutOfMemoryError ● Profiler ● Class or heap dump analyze such as Java Object Layout
  • 4. 4 Runtime.getRuntime().freeMemory() ● Get allocated memory stats ● Create new objects ● Call GC many times ● Get allocated memory difference ● Not very precise, but easy ● May not always work, some JVMs ignore System.gc() NanoBench nanoBench = NanoBench.create(); nanoBench.memoryOnly().warmUps(2).measurements(10) .measure(String.format("Measure memory for %d keys", i), new Runnable() { @Override public void run() { Random setRandom = new Random(4532); ref = new HashSet<Integer>(cnt); w hile (ref.size() < cnt) { ref.add(setRandom.nextInt()); } } }); nanoBench.getMemoryBytes()
  • 5. 5 OutOfMemoryError ● Memory limit (-Xmx1G) ● Add entries to array in loop ● Print number of items ● JVM eventually crashes try{ //add new entry in loop while(true) array[arrayPos++] = new HashMap(); }catch(OutOfMemoryError e){ memoryConsumption = Runtime.getRuntime().maxMemory() / counter; return; }
  • 6. 6 Profiler ● Shows memory consumed by single class – (byte[], Object[]) ● VisualVM is easy to use ● Flight Recorder is best – Free outside production env.
  • 7. 7 Java Object Layout ● Command line tool to analyze memory layout (and space usage) ● Most advanced ● http://openjdk.java.net/projects/code-tools/jol/ ● Written by Aleksey Shipilev ● Example: $ java -jar jol-cli/target/jol-cli.jar internals java.util.HashMap Instance size: 48 bytes (reported by Instrumentation API) Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
  • 8. 8 Instance overhead in Java ● Pointer overhead – 4 to 8 bytes – depends on JVM and amount of memory – 64bit JVM 8 uses compressed pointer when possible ● Class info and object header – 12 bytes ● Object alligment padding – Between 0 and 15 35 bytes worst case scenario
  • 9. 9 java.lang.Integer overhead ● One object + one reference ● Total overhead 16 bytes + reference (4 to 8 bytes) JOL output for java.lang.Integer OFFSET SIZE TYPE DESC 0 12 (object header) 12 4 int Integer.value total size: 16 bytes
  • 10. 10 java.lang.String overhead ● Two objects and two references ● One int field (String.hash) ● Two bytes per char (UTF16) ● Other problems: – Weak hash (many collisions) – Defensive char[] copies – Substring create copies etc.. JOL output for java.lang.String OFFSET SIZE TYPE DESC 0 4 (object header) 4 4 (object header) 8 4 (object header) 12 4 char[] String.value 16 4 int String.hash 20 4 (alignment loss) total size: 24 bytes
  • 11. 11 String.intern() ● Reduces number of instances ● Each string creates new weak ref (huge GC overhead) ● Long.valueOf(11) is similar name.toLowerCase().intern() == name.toLowerCase().intern()
  • 12. 12 Represent String as char[] ● Field is char[] or byte[] ● Get/set takes string ● GC overhead, but short lived objects are fast to collect ● Reduced memory with many objects (large Maps etc) public class Person{ private char[] name; public String getName(){ return new String(name); } public void setName(String name){ this.name = name.toCharArray(); } }
  • 13. 13 char[] as key in Map ● char[] has no equals() and hashCode() methods ● TreeMap key can use Comparator<char[]> – com.google.common.primitives.Chars.lexicographicalComparator() ● java.util.HashMap can not change hash strategy – Object2ObjectOpenCustomHashMap from FastUtil has Hash Strategies – String.hashCode() is broken, many collisions ● Part of spec, can not be changed :-( ● ConcurrentHashMap Java8 has sorted lists to handle hash duplicates :-)
  • 14. 14 char[] as value in Map ● Works (mostly) ● Concurrent Compare-And-Swap operations broken – char[].equals() uses identity – ConcurrentMap.replace(K key, V oldValue, V newValue); – MapDB Maps allow custom equality
  • 15. 15 Bitwise class Address{ String street; int houseNumber; } ● Replace street with number from dictionary ● Combine streetId and houseNumber into single long number – 5 bytes for streetId, 3 bytes for house number and flags ● Adress become primitive number, no objects or references
  • 16. 16 Primitive key / value in collections ● HashMap<Long,Long> uses Object[] for keys and values ● ~40 bytes overhead for each key-value pair ● Use long[] or int[] instead ● Data locality → CPU cache friendly – Binary search much faster – Faster fetch of values ● Almost zero Garbage Collection – entire HashMap uses two objects – No objects allocated for new key or value
  • 17. 17 FastUtil ● http://fastutil.di.unimi.it/ ● Autogenerated classes with primitive keys and values ● Int2IntMap, Int2BooleanMap, Int2ObjectMap<V> …. ● Many classes, 17MB jar
  • 18. 18 FastUtil // create new map Int2ObjectMap<String> map = new Int2ObjectOpenHashMap(); // put/get has primitive arg, no unboxing! map.put(1, "aa"); map.get(1); // also implements full mapdb interface Map<Integer, String> map2 = map; ● Parallel interface hierarchy ● Get / set has primitive arg version, no unboxing! ● Implements Map interface
  • 19. 19 Chronicle Map ● ConcurrentHashMap ● Keys and values are serialized outside heap ● Supports any serializable data type ● No objects or references on heap, memory efficient ● http://chronicle.software/product s/chronicle-map/ Map<Long, long[]> graph = ChronicleMap .of(Long.class, long[].class) .entries(1_000_000_000L) .averageValue(new long[150]) .create();
  • 20. 20 Conclusion ● Avoid too many object instances in long lived objects ● Short lived objects are fine, when traded for smaller memory ● Email: [email protected] ● Slides and code at – https://github.com/jankotek/talk-save-java-memory