Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a good logging library for real-time systems (fast with no object creation)?

I tried logback but it created a ton of garbage. Does anyone heard about a good one for real-time Java?


@Bernie: I did a loop logging 1M cached messages and the GC went crazy.

like image 945
JohnPristine Avatar asked Dec 03 '22 04:12

JohnPristine


2 Answers

I have a library which can log text or binary data in under a micro-second without creating garbage or even a system call.

https://github.com/peter-lawrey/Java-Chronicle

The log can also be read in real time by any number of reading processes, giving you a persisted queue which can handle over 5 million messages per second.

like image 159
Peter Lawrey Avatar answered Dec 09 '22 14:12

Peter Lawrey


You can take a look on CoralLog designed by Coral Blocks (with which I am affiliated) that produces zero garbage and has an average latency of 53 nanoseconds when logging a 64-byte message. In terms of throughput, it can log 2.6 million 64-byte messages per second with timestamps and 3.5 million 64-byte messages per second without timestamps. The complete benchmark results can be seen here.

If you reduce the message size to 16 bytes then you can log 5.2 million messages per second without timestamps.

Below is a simple throughput test:

package com.coralblocks.corallog.bench;

import java.io.File;
import java.nio.ByteBuffer;

import com.coralblocks.corallog.AsyncThread;
import com.coralblocks.corallog.Log;
import com.coralblocks.corallog.Logger;

public class PerformanceTest4 {

    public static void main(String[] args) throws Exception {

        int batchSize = Integer.parseInt(args[0]);
        int passes = Integer.parseInt(args[1]);
        int msgSize = Integer.parseInt(args[2]);

        byte[] msgBytes = new byte[msgSize];

        // build a dummy message:
        for(int i = 0; i < msgBytes.length; i++) {
             msgBytes[i] = (byte) String.valueOf(i % 10).charAt(0);
        }

        ByteBuffer bb = ByteBuffer.wrap(msgBytes);

        Log.setIncludeTopHeader(false);

        String dir = ".";
        String filename = "throughput.log";

        Logger logger;
        boolean isMmap = System.getProperty("logMemoryMappedFile", "true").equals("true");

        if (isMmap) {
            logger = Log.createMemoryMappedLogger(dir, filename, null /* no timestamps */, false /* not synchronized */, true /* asynchronous */);
        } else {
            logger = Log.createLogger(dir, filename, null, false, true);
        }

        int count = 0;

        while(count < passes) {

            long start = System.nanoTime();

            for(int i = 0; i < batchSize; i++) {
            bb.position(0);
            logger.log(bb);
            }

            long time = System.nanoTime() - start;

            double seconds = (((double) time) / 1000000000L);

            System.out.println("Batch " + (count + 1) + " took: " + seconds + " s");

            count++;
        }

        logger.drainCloseAndWait();

        boolean deleteFile = System.getProperty("deleteFile", "true").equals("true");

        if (deleteFile) {
            File f = new File(dir, filename);
            f.delete();
        }

        AsyncThread.drainAndDie(); // just so the vm will exit... (async thread is not daemon)
    }
}
like image 44
rdalmeida Avatar answered Dec 09 '22 14:12

rdalmeida