-2

com.offbynull.coroutines version 1.1.0 consumers only consumes 7500 messages.

Please help me understand why this code only consumes 7500 messages instead of 30000.


public class DemoProducerConsumer {

    public static int cnt = 0;
    public static final int MAX = 10000;

    public static class Producer implements Coroutine {

        @Override
        public void run(Continuation ctn) throws Exception {
            String thName = Thread.currentThread().getName();
            System.out.println(thName + ") Producer starting...");
            Consumer consumer = new Consumer();
            for (int i = 0; i < 3; i++) {
                consumer.consume(ctn, "Hello:" + i);
            }
            System.out.println(thName + ") Producer published 3 messages");
        }
    }

    public static class Consumer {    
        public void consume(Continuation ctn, String message) {
            String thName = Thread.currentThread().getName();
            System.out.println(thName + ")" + message);
            cnt++;  // <<< SUSPECT bug here.
            ctn.suspend();  // <<< SUSPECT bug here.
        }
    }

    public static final void main(String... args) throws InterruptedException {

        String thName = Thread.currentThread().getName();
        System.err.println(thName + ") Preparing Producer ");

        new Thread(new Runnable() {
            public void run() {
                cnt = 0;
                Producer producer = new Producer();
                CoroutineRunner runner = new CoroutineRunner(producer);
                for (int i = 0; i < MAX; i++) {
                    runner.execute();
                }
                System.out.println(thName + ") Producer Looped " + MAX + " times.");
            }
        }).start();
        System.err.println(thName + ") Waiting " + (MAX * 3) + " message to be consumed...");
        Thread.sleep(10000);
        System.err.println(thName + ") Message consumed:" + cnt);
        System.err.println(thName + ") Exiting...");
    }    
}

I plan to use this with Thread Pool to implement a higher performance MVC server.

Separation of consumer and producer is a must.

mas4
  • 989
  • 1
  • 8
  • 20
Matthew Ong
  • 104
  • 8

1 Answers1

1

Author of coroutines here. You seem to be misunderstanding how the execute() method works. Everytime you call suspend(), execute() will return. When you call execute() again, it'll continue executing the method from the point which you suspended.

So, if you want to completely execute your coroutine MAX times, you need to change your main loop to the following:

for (int i = 0; i < MAX; i++) {
    boolean stillExecuting;
    do {
        stillExecuting = runner.execute();
    } while (stillExecuting);
}

In addition to that, since you're accessing the field cnt from separate threads, you should probably be marking cnt as volatile:

public static volatile int cnt = 0;

Running with the above changes produces what you expect for your output:

main) Producer Looped 10000 times.
main) Message consumed:30000
main) Exiting...

Also, you should spend some time evaluating whether coroutines are a good fit for your usecase. I don't understand the problem you're trying to solve, but it sounds like normal Java threading constructs may be a better fit.

offbynull
  • 381
  • 3
  • 16
  • Hi. Thanks for the reply. I was using it to profile for at least a C10K web performance issue(request/pull from db and process/reply model). Compared to other library like Kilim and Reactor. I understand that Coroutines suppose to work in a more smoothly than multithreadeds with plenty of thread context switching. – Matthew Ong Jun 08 '15 at 02:56
  • The above sample code: Producer(Controller of MVC) and Consumer(The Model or DAO layer). The local call without sockets is just for test sample code. – Matthew Ong Jun 08 '15 at 02:59
  • I am also profiling coroutine against other library such as: https://github.com/jetlang/core – Matthew Ong Jun 08 '15 at 03:00