DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Coding
  3. Java
  4. Java Holiday Calendar 2016 (Day 20): Break Out of the Java Heap

Java Holiday Calendar 2016 (Day 20): Break Out of the Java Heap

Moving data off the heap, within reason, can let you work more efficiently while keeping latency low. That way, you can avoid the garbage collection wall for longer.

Per-Åke Minborg user avatar by
Per-Åke Minborg
·
Dec. 20, 16 · Tutorial
Like (8)
Save
Tweet
Share
6.02K Views

Join the DZone community and get the full member experience.

Join For Free

Image title

Today's tip is about storing things off heap. As we all know, Java will occasionally clean up the heap (i.e. invoke its Garbage Collector or GC for short) and remove objects that are no longer used. As the heap grows, so will the time it takes to clean it up. Eventually, the GC will take seconds or minutes, and we have hit "the GC wall". Historically, this was a problem for heaps above 10 GB of data, but nowadays we can have larger heaps. How big depends on a vast number of factors.

One way of reducing GC impact is to store data off heap, where the GC is not even looking. This way, we can grow to any data size without caring about the GC. The drawback is that we have to manage our memory manually and also provide a means of converting data back and forth between the two memory regions. In general, this is a bit tricky, but if we limit ourselves to the primitive types like int, long, double, and the likes, it is fairly easy.

Consider the following OffHeapIntArray:

public final class OffHeapIntArray implements Iterable<Integer> {
    private final IntBuffer buffer;
    private final int length;
    public OffHeapIntArray(int length) {
        if (length < 0) {
            throw new IllegalArgumentException();
        }
        this.length = length;
        /* Allocates memory off heap */
        this.buffer = ByteBuffer.allocateDirect(length * Integer.BYTES)
            .asIntBuffer();
    }

    public int get(int index) {
        return buffer.get(index);
    }

    public void set(int index, int value) {
        buffer.put(index, value);
    }

    public int length() {
        return length;
    }

    @Override
    public PrimitiveIterator.OfInt iterator() {
        return new Iter();
    }

    @Override
    public void forEach(Consumer<? super Integer> action) {
        for (int i = 0; i < length; i++) {
            action.accept(i);
        }
    }

    @Override
    public Spliterator.OfInt spliterator() {
        return Spliterators.spliterator(iterator(), length,
            Spliterator.SIZED
            | Spliterator.SUBSIZED
            | Spliterator.NONNULL
            | Spliterator.CONCURRENT
        );
    }

    public IntStream stream() {
        return StreamSupport.intStream(spliterator(), false);
    }

    private final class Iter implements PrimitiveIterator.OfInt {
        private int currentIndex;
        public Iter() {
            currentIndex = 0;
        }

        @Override
        public int nextInt() {
            if (hasNext()) {
                return get(currentIndex++);
            }
            throw new NoSuchElementException();
        }

        @Override
        public void forEachRemaining(IntConsumer action) {
            while (currentIndex < length) {
                action.accept(get(currentIndex++));
            }
        }

        @Override
        public boolean hasNext() {
            return currentIndex < length;
        }

        @Override
        public Integer next() {
            return nextInt();
        }
    }
}


As you can see, it stores all the int elements off heap and allows us to do a number of things like this:

    public static final void main(String... args) {
        final OffHeapIntArray array = new OffHeapIntArray(10);
        array.set(0, 100);
        array.set(1, 101);
        array.set(9, 109);

        System.out.println("** Iterate **");
        for (int val : array) {
            System.out.println(val);
        }

        System.out.println("** Stream **");
        array.stream()
            .filter(i -> i > 0)
            .forEach(System.out::println);
    }


This will produce the following output:

** Iterate **
100
101
0
0
0
0
0
0
0
109

** Stream **
100
101
109


It is possible to create more advanced off heap classes, like OffHeapMap, OffHeapArrayList, etc., that store all data off heap in a similar way. Speedment Enterprise is using a more advanced version of this technology to be able to store large databases as in-JVM-memory objects. In fact, it is possible to store more data than the available RAM since byte buffers can be mapped onto files. This opens up the path to mammoth JVMs with terabytes of data available at ultra-low latency.

Follow the Java Holiday Calendar 2016 with small tips and tricks all the way through the winter holiday season. I am contributing to open-source Speedment, a stream based ORM tool and runtime. Please check it out on GitHub.

Java (programming language) Calendar (Apple)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Silver Bullet or False Panacea? 3 Questions for Data Contracts
  • The Real Democratization of AI, and Why It Has to Be Closely Monitored
  • Agile Scrum and the New Way of Work in 2023
  • Implementing Infinite Scroll in jOOQ

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: