Как я могу передавать сообщения в другой поток, не используя очередь блокировки? - PullRequest
3 голосов
/ 07 ноября 2011

У меня довольно простой сервер (использующий крионет).Клиенты хранят только текущее состояние автомобиля (x, y, угол и т. Д.) И отправляют запросы на ускорение и поворот.

Сервер получает запросы и добавляет их в ArrayBlockingQueue, который физический потокистощает, читает и обновляет.

При добавлении другого игрока скорость игры замедляется почти вдвое.Я исключил много вещей (у меня все обновления и посылки посажены на частоте 60 Гц.)

Я подозреваю, что использование очереди блокировки блокирует настолько, что вызывает замедление.

Как я могу отправлять клиентские запросы в физический поток, не блокируя проблемы?

Ответы [ 5 ]

2 голосов
/ 07 ноября 2011

Я подозреваю, что использование очереди блокировки блокирует настолько, что вызывает замедление.

Вы подозреваете, что это неправильно. Следующая тестовая программа проталкивает 1 миллион целых чисел через 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();
    }
}

На моем ноутбуке он заканчивается через пару секунд. Поэтому, где бы ни было ваше узкое место в производительности, это не ArrayBlockingQueue, который может обрабатывать пропускную способность как минимум на 3 порядка выше, чем вам нужно. Иными словами, даже если вы нашли подход к обмену потоками, который вообще не требует времени выполнения, это только ускорит вашу программу максимум на 0,1%.

Возьмите домашний урок для решения этой и всех других проблем с производительностью. Первый шаг при решении любой проблемы с производительностью в существующем коде - измерить, какая часть кода медленная , как обычно, это не где надеется. Профилировщики значительно упрощают эту задачу.

1 голос
/ 08 ноября 2011

Я нашел ошибку.Мне нужно было регулировать физическое моделирование другим способом (не с помощью функции world.step (), но ограничивать частоту его вызова).Это что-то вроде этого.

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

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

        processAndUpdateYourData();

        timer = System.nanoTime();
    }
}

Тогда мне нужно настроить все физические числа, чтобы они выглядели естественно в этой конфигурации.

1 голос
/ 07 ноября 2011

Вы можете использовать разрушитель (кольцевой буфер), механизм без блокировки для реализации очереди.См .:

0 голосов
/ 07 ноября 2011

Убедитесь, что вы создаете очередь с достаточным количеством доступных слотов, чтобы удовлетворить всех клиентов.Если очередь заполняется из-за слишком большого количества клиентов, они будут блокироваться при попытке вставить команды.Если это не проблема, это означает, что ваш физический (потребительский) поток не поспевает за запросами, и вам нужно убедиться, что он получает больше времени на обработку.

0 голосов
/ 07 ноября 2011

Ваш вопрос предполагает реализацию - вам лучше задать вопрос "почему мой код такой медленный?"

Я бы добавил больше потребительских потоков - попробуйте добавить столько потребительских потоков, сколько имеется процессорных ядер - т.е. Runtime.getRuntime().availableProcessors().

...