offbynull / coroutines

Java toolkit that allows you to write coroutines.
GNU Lesser General Public License v3.0
345 stars 53 forks source link

Please consider opening up ThreadPool replacement with other custom pool #48

Closed gencube closed 9 years ago

gencube commented 9 years ago

Hi,

I do like your methods of Design but prefers NOT to have any Bytecode instrumentation:

Please have a look at here, Example of using Transformer: https://github.com/perwendel/spark

public class JsonTransformer implements ResponseTransformer {
    private Gson gson = new Gson();
    @Override
    public String render(Object model) {
        return gson.toJson(model);
    }
}
..
public class TransformerExample {
    public static void main(String args[]) {
        get("/hello", "application/json", (request, response) -> {
            return new MyMessage("Hello World");
        }, new JsonTransformer());
    }
}

There is a clean pattern to allow that for your library to be customized:

public class MyRoutineEngine implements RoutineEngine {
  public void before(Routine ajob){}
  public void run(Job ajob){}
  public void after(Job ajob){}
}
...
routineEngine(new MyRoutineEngine());
gencube commented 9 years ago

BTW, this is also me: http://stackoverflow.com/questions/30364631/offbynull-coroutines-not-consuming-all/30697676#30697676

offbynull commented 9 years ago

You can't do what this library does without either bytecode instrumentation or native calls. It's impossible with the current version of Java. The only way you could get around it is by explicitly writing out your method logic as a FSM, which is going to be incredibly painful to understand/maintain. You can see an example of what I mean by looking at the Javadoc header for this class: https://raw.githubusercontent.com/offbynull/peernetic/master/core/src/main/java/com/offbynull/peernetic/core/actor/CoroutineActor.java

With regards to your SO comment: "I understand that Coroutines suppose to work in a more smoothly than multithreadeds with plenty of thread context switching."

This is not correct. In nearly all cases, standard Java threads are the way to go. Coroutines have a very narrow/niche set of usecases which they're well-suited for. The main usescases are:

  1. Systems that require cooperative multithreading because preemptive multithreading isn't available (for example, embedded systems where java.lang.Thread doesn't exist).
  2. Actor-based systems where you have a very high number of actors and each actor reacts to messages that it receives. In this case, each actor would be a coroutine rather than a basic Java thread, and many coroutines would run on a single Java thread. The coroutines project was created specifically to satisfy this usecase: see the peernetic project.
  3. Game AI, where a game loop that's running x number of times per second requires each game NPC to perform some AI calculation during each loop. This is similar to the usecase presented above. More information on this usecase can be found by reading the unity documentation: http://docs.unity3d.com/Manual/Coroutines.html

In any event, it almost sounds like what you're looking for is a library to perform fast message-passing between Java threads. This library won't help you with that. In fact, this library was written in a way to avoid anything and everything to do with standard Java threads. It's purely a library for software-based cooperative multithreading -- it doesn't do anything with Java/OS threads or threading constructs such as locks.

This may be a better fit for your performance requirements: https://lmax-exchange.github.io/disruptor/. It's a library that does high-performance message passing between Java threads.

gencube commented 9 years ago

Thanks very much to take the time and explained to me the detail of this matter. Really appreciate your effort. I will look into the disruptor model.

Just FYI, the reason I had a misunderstanding is because of this:

https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

But why?

We seem to have understood in other parts of computing recently that less is more. Why is it that with only 4-threads an nginx web-server can substantially out-perform an Apache web-server with 100 processes? Isn't it obvious if you think back to Computer Science 101?

Even a computer with one CPU core can "simultaneously" support dozens or hundreds of threads. But we all [should] know that this is merely a trick by the operating system though the magic of time-slicing. In reality, that single core can only execute one thread at a time; then the OS switches contexts and that core executes code for another thread, and so on. It is a basic Law of Computing that given a single CPU resource, executing A and B sequentially will always be faster than executing A and B "simultaneously" through time-slicing. Once the number of threads exceeds the number of CPU cores, you're going slower by adding more threads, not faster.