reggaemuffin
reggaemuffin

Reputation: 1198

What is the fastest data storage to pass a group of objects from one thread to another?

I have two threads, one reading streams and producing data-objects from their content.

I then have to pass them to the second thread, writing them into a database.

I want to separate the two tasks (that's why I took two threads) because I/O-Performance on the streams and the database varies. In some cases, the stream is fast, sometimes, the db has some lag.

So I thought of putting some (very simple!) data-storage between them.

My first idea was a FILO-solution, has to be Thread-safe and should be fast (no fancy stuff, just put and pull). The order does not matter. At some time there could be around 100,000 Entries in the storage (that would be the case after around one second ping with the db).

Each object has a small footprint, <1kb.

What would you recommend to me?

Upvotes: 3

Views: 141

Answers (2)

Rafael Baptista
Rafael Baptista

Reputation: 11499

Don't copy your objects between threads. Pass pointers to the objects between the threads. And try to keep objects sequential in memory. This way when you pass a batch of objects between threads the CPU only has to remap a few memory pages between CPUs.

Pass the objects between threads in batches that are larger than the OS memory page size.

So for ideal performance you want the producer to be using one set of memory pages, and the consumer using another set of pages. The CPU will make sure that the pages used by one core are mapped to local storage on that core, and other pages on the other core.

If you don't do this, then memory pages are ping-ponging back and forth between cores.

If you copy, then it is the same. As the writer thread writes to one page, and the reader thread is reading on the same page, the CPU is spending time making sure both cores see the same data.

So I'd have the reader read a bunch of objects say 16k worth, and not make them available to the consumer thread. Once you've filled those pages, release them to the processor thread, and allocate another 16k block of data to start filling with more objects.

Upvotes: 1

Petar Minchev
Petar Minchev

Reputation: 47383

This is exactly the producer-consumer pattern. Take a look at BlockingQueue and its implementations.

Here is sample code from my blog:

public class Producer implements Runnable {
    private BlockingQueue queue;

    public Producer(BlockingQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        //Produce 1000 products
        for (int i = 0; i < 1000; i++) {
            queue.put(new Product());
            System.out.println("PRODUCED PRODUCT");
        }
    }
}
public class Consumer implements Runnable {
    private BlockingQueue queue;

    public Consumer(BlockingQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            Product product = queue.take();
            System.out.println("CONSUMED PRODUCT");
        }
    }
}

And here is the calling code:
BlockingQueue queue = new ArrayBlockingQueue(50);

Producer producer = new Producer(queue);
new Thread(producer).start();

Consumer consumer = new Consumer(queue);
new Thread(consumer).start();

Upvotes: 5

Related Questions