views:

124

answers:

6

Suppose I have a Java method like:

public Ouput respond(Input input) { /* .. */ }

The Output object has many fields - some of those fields depend on the Input object but the rest are pre-determined. I want to make the thread which calls respond() to return as fast as possible.

For this I want to spawn another thread which pre-creates Output object, sets some of the fields and puts them in a queue so that the thread running respond() can pick it up from the queue, set the remaining fields and return it.

What is the best way to implement something like this? My current prototype uses a bounded LinkedBlockingQueue but are there better ways to implement this idea?

My aim is to get the respond() method as fast as possible, so other suggestions which meet that goal are also welcome. :-)

+2  A: 

Maybe you can adapt your implementation that Output-objects do not have to be created for every respond()-call but to recycle Output-objects when they are not needed anymore. Resetting fields should be faster than creating them from scratch and if you have a high object-throughput it also saves you some time in the garbage-collection and you can also improve cache-performance of the processor and Java VM.

Of course this can only work if you can control the whole process and can change the caller who gets the result of respond().

But if you really have such high performance-requirements this could be another idea to play around with. Just don't make it too complicated to be maintainable anymore.

Kosi2801
@Kosi2801 Unfortunately, I have no control over the lifecycle of the created object so object-pooling might not be easy to implement in my case. Nonetheless, it is something I should think about - thanks for bringing it up!
binil
+3  A: 

This sounds like a case where you could make good use of Futures and Executors. See more here:

Here's a concrete example:

ExecturService executor = Executors.newSingleThreadExecutor();

final Input input = ...
Future<Output> future = executor.submit(new Callable<Output>() {
  public Output call() {
    return respond(input);
  }
});

// do some work

Output output = future.get();  // this blocks until it's done

In your case, since you mentioned that some of the fields in the Output object are to be used immediately, while others are used at a later point, you could structure your Output object to contain futures as fields. For example:

public class Output {
   private String fieldA; // immediate field
   private Future<String> fieldB; // delayed field

   public void setFieldA(String fieldA) { this.fieldA = fieldA; }
   public String getFieldA() { return fieldA; } 
   public void setFieldB(Future<String> fieldB) { this.fieldB = fieldB; }
   public Future<String> getFieldB() { return fieldB; }
}

You'd then structure your respond method like this:

public Output respond(final Input input) {
   Output output = new Output();
   String fieldA = ...
   output.setFieldA(fieldA);

   Future<String> fieldBFuture = executor.submit(new Callable<String>() {
     public String call() {
       String fieldB = ...
       return fieldB;
     }
   }

   output.setFieldB(fieldBFuture);
}

And to use your Output object:

Input input = ...
Output output = respond(input);

String fieldA = output.getFieldA();
// do some work
String fieldB = output.getFieldB().get();
toluju
@toluju I did not understand how `Executor`s can be useful in this context - can you please outline the algorithm?
binil
@binil Added example for you, let me know if that clears things up.
toluju
toluju, binil mentioned above that `Output` is provided by a 3rd-party library to which he has no source access; it looks like this method would require him to be able to modify the class, which he can't do.
delfuego
Right, I forgot that part. You could still wrap the original `Output` class to accomplish the same task though.
toluju
A: 

If the rest of the fields are truly "pre-determined" why not make them static on the Output class?

David Soroko
By "pre-determined" I meant that they don't depend on `Input`, but can be determined even before anyone calls `respond()`.
binil
Do they differ between respond() calls?
David Soroko
+1  A: 

Why not create an object-creation factory that, on construction, pre-populates an internal store of Output objects, doles them out on request, and contains logic to know when it's necessary to repopulate the internal store? Perhaps something like this (note that this is just off-the-top-of-my-head simplecode; there are clear places where you can do a lot more, like have specific algorithms to determine when the pool has too few objects, synchronize on repopulation, etc.):

public class OutputFactory {

    private List<Output> outputPool = new LinkedList<Output>();

    public OutputFactory() {
        this.populatePool();
    }

    private void populatePool() {
        // spawn a new thread here, if you wish, to optimize time-to-return
        for (int i = 0; i < 100; i++) {
            outputPool.add(new Output());
        }
    }

    public Output getNewOutput() {
        Output newOutput = outputPool.remove(0);
        if (outputPool.size() < 10) {
            populatePool();
        }
        return newOutput;
    }

}
delfuego
This would block every 100th request when the pool has to be refilled and that's not the intended behaviour. I guess that's the reason why the Asker refers to another thread for the Output-generation, so that every request() returns as fast as possible and not only 99 out of 100.
Kosi2801
Kosi2801, that's why I said that you could spawn a new thread there if you wanted to and return immediately; I just wrote it out as pseudo/simplecode to convey the entire idea.
delfuego
Sorry, overlooked that.
Kosi2801
+1  A: 

Since all threads are sharing the same heap, I can't imagine that creating them on a different thread is going to make much of a difference as far as allocation is concerned. If you are seeing a benefit from threading, it would be due to whatever computation is required to set the pre-determined fields on the Output object.

If that's the case, you might do even better to have a single template Output object with the predetermined fields pre-filled, and then simply have respond() clone the shared template object. (If the object is not already Cloneable and you can't make it so, it would cost about the same to copy the fields yourself.)

If the template thing doesn't work, but you could recycle Output instances, that's probably an even better option, as no new memory needs to be allocated at all, and the predetermined fields don't even need to be copied; they will already be set.

Either of those strategies would allow you to speed up the respond() method without the overhead of a separate thread.

benzado
@benzado You are right that allocation is going to take the same amount of time, irrespective of which thread I do it on. I am trying to improve the perceived performance of the respond() method by doing the allocation earlier. Think of it like a fast-food restaurant - the food takes the same amount of time to cook regardless of when you cook it, but the customers perceive faster service if you have the food cooked ahead-of-time.
binil
It's not "perceived" performance, it's latency that you're trying to improve. Anyway, both the methods I suggested should help in that regard.
benzado
+2  A: 

Unless creating the object used by fields of Output are fairly expensive, the cost of using another thread will be many times greater than the cost of setting a few fields.

Peter Lawrey