В моем приложении есть несколько служб, которые обрабатывают информацию в своем потоке, когда они сделаны, они отправляют сообщение следующей службе, которая затем продолжает выполнять свою работу в своем потоке. Передача сообщений осуществляется через LinkedBlockingQueue. Обычно передача обслуживания занимает 50-80 секунд (от ввода сообщения в очередь до тех пор, пока потребитель не начнет обрабатывать сообщение). Чтобы ускорить передачу обслуживания в наиболее важных службах, я хотел использовать занятый спин вместо блокирующего подхода (у меня есть 12 процессорных ядер и вы хотите посвятить 3 этим важным сервисам). Итак, я изменил LinkedBlockingQueue на ConcurrentLinkedQueue
и сделал
for(;;)
{
Message m = queue.poll();
if( m != null )
....
}
Теперь... результат состоит в том, что первое сообщение проходит 1 us, но тогда латентность увеличивается в течение следующих 25 передач до тех пор, пока не достигнет 500 us, а затем латентность внезапно возвращается к 1 us и начинает увеличиваться. У меня есть латентные циклы с 25 итерациями, где латентность начинается с 1 us и заканчивается на 500 us. (сообщение передается приблизительно 100 раз в секунду)
со средней задержкой в 250 баллов это не совсем то, что я искал.
Я также пытался использовать кольцевой буфера LMAX Disruptor вместо ConcurrentLinkedQueue. У этой фреймворка есть своя собственная сборка в занятой спиновой реализации и совсем другая реализация очереди, но результат был тот же. Так что я совершенно уверен, что это не вина в очереди или меня что-то злоупотребляю..
Вопрос.. Что здесь происходит? Почему я вижу эти странные латентные циклы?
Ура!!