Question

I have a pretty straight forward server (using kryonet). The clients are only storing the current state of the car (x,y,angle etc) and are sending requests of acceleration and turning.

The server is receiving the requests and adding them to a ArrayBlockingQueue that the physics thread drains and reads and updates.

When adding another player, the speed of the game slows down by almost double. I have ruled out a lot of things (I have all updates and package sending throttled at 60Hz.)

I am suspecting that using a blocking queue is blocking so much that it is causing the slowdown.

How can I send the client requests to the physics thread without blocking issues?

Was it helpful?

Solution 3

I have found the bug. I needed to throttle the physics simulation in a different way (not with the world.step() function, but limit how often that is called). It is something like this.

while(true)
{
    delta = System.nanoTime() - timer;

    if(delta >= 16666666) // 60 Hz
    {
        world.step(1.0f, 6, 2);

        processAndUpdateYourData();

        timer = System.nanoTime();
    }
}

Then I need to adjust all the physics numbers so they feel natural with this configuration.

OTHER TIPS

I am suspecting that using a blocking queue is blocking so much that it is causing the slowdown.

You suspect wrong. The following test program pushes 1 million Integers through an ArrayBlockingQueue:

public class ArrayBlockingQueuePerfTest {
    int maxi = 1000000;

    ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1000,
            true);

    Thread sender = new Thread("sender") {
        public void run() {
            try {
                for (int i = 0; i < maxi; i++) {
                    queue.offer(i, 1, TimeUnit.SECONDS);
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };
    };
    Thread receiver = new Thread("receiver") {
        public void run() {
            try {
                int count = 0;
                long sum = 0;
                while (count < maxi) {
                    sum += queue.poll(1, TimeUnit.SECONDS);
                    count++;
                }
                System.out.println("done");
                System.out.println("expected sum: " + ((long) maxi) * (maxi - 1) / 2);
                System.out.println("actual sum:   " + sum);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };
    };

    public ArrayBlockingQueuePerfTest() {
        sender.start();
        receiver.start();
    }

    public static void main(String[] args) {
        new ArrayBlockingQueuePerfTest();
    }
}

On my laptop, it terminates in a couple seconds. So wherever your performance bottleneck is, it is not the ArrayBlockingQueue, which could handle a throughput at least 3 orders of magnitude higher than you need. Put differently, even if you found a thread communication approach that takes no execution time at all, that would only speed up your program by at most 0.1%.

Take home lesson for this and all other performance problems: The first step when tackling any performance problem in existing code is to measure which part of the code is slow, as usually, it is not where one expects. Profilers simplify this task greatly.

You can use a disruptor (ring buffer), a lock-free mechanism for implementing a queue. See:

Your question presupposes an implementation - you would be better to ask "why is my code so slow?".

The blocking queue is the most efficient way of implementing the producer/consumer pattern.

I would add more consumer threads - try adding as many consumer threads as there are processor cores - ie Runtime.getRuntime().availableProcessors().

Make sure you are creating the queue with enough slots available to satisfy all the clients. If the queue becomes full because there are too many clients, they will block when trying to insert commands. If that's not the problem it means your physics (consumer) thread is not keeping up with the requests and you need to make sure it gets more processing time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top