По зрелому размышлению я пришел к выводу, что card marking здесь не при делах. У меня же ссылки в массив пишутся только одним потоком -- который выполняет enqueue. Вот если бы я на dequeue очищал ссылку в null (как, собственно, стоило бы делать в production-ready коде) -- тогда другое дело. Но же я выкинул очистку на одной из первых оптимизаций -- так что у меня по любому single writer получается.
А вот как проверить, что сама запись ссылки порождает 10% оверхеда -- мне пришло в голову вчера. Все довольно просто: у меня же очереди используют пул сообщений (чтобы не плодить лишнюю аллокацию). Пул, естественно, имеет тот же размер, что и очередь (зачем ему больше?), поэтому после первого же прохода все элементы во внутреннем буфере очереди фиксированы -- на следующих проходах они перезаписываются поверх себя же. Достаточно вместо set сделать там test-and-set -- и можно будет проверять.
Эксперименты были запущены, и -- бинго! -- наконец-то мы совершенно догнали Д :) 30*10^6 msg/sec. Предположение о том, что во всем (в оставшихся 10%) виновата запись ссылки в буфер таким образом, похоже, оправдывается. Процесс разборки магии Д на компоненты на этом можно считать закрытым.
Единственное, что остается для меня все еще не понятным -- это нестабильность результатов. Типичные результаты запуска выглядят так:
Turn # 1 takes 67058 ms; 7456232 ops/sec
Turn # 2 takes 15854 ms; 31537782 ops/sec
Turn # 3 takes 16058 ms; 31137128 ops/sec
Turn # 4 takes 16201 ms; 30862292 ops/sec
Turn # 5 takes 16111 ms; 31034697 ops/sec
Turn # 6 takes 15794 ms; 31657591 ops/sec
Turn # 7 takes 60603 ms; 8250417 ops/sec
Это совершенно не похоже на нормальное распределение вокруг среднего :) Ощущение, что система может функционировать в одном из 2 режимов -- либо все хорошо, либо случается какое-то гавно.
Это, похоже, JIT: сначала соптимизировал, потом попытался еще, но только ухудшил.Я такое видел на своих программах (тоже передача сообщений).
ОтветитьУдалитьЛюбопытно. Я гляну, хотя кажется маловероятным -- все-таки слишком заметное изменение. К тому же непонятно, почему в некоторых запусках стабильно высокие результаты -- JIT же вполне предсказуемый
ОтветитьУдалитьУвы, предположение не оправдывается -- со включенным PrintCompilation никаких сообщений о деоптах на переходе между "быстрым" и "медленным" не выдается
ОтветитьУдалить