Проблема здесь в ложных указателях. Сборщик мусора D консервативный, то есть он не всегда знает, что является указателем, а что нет. Иногда нужно предположить, что битовые комбинации, которые указывали бы на выделенную GC память, если интерпретировать их как указатели, являются указателями. Это в основном проблема для больших распределений, так как большие блоки являются большей целью для ложных указателей.
Вы выделяете около 48 МБ каждый раз, когда звоните testA()
. По моему опыту этого достаточно, чтобы почти гарантировать, что в 32-битной системе будет ложный указатель на блок. Вероятно, вы получите лучшие результаты, если скомпилируете свой код в 64-битном режиме (поддерживается в Linux, OSX и FreeBSD, но пока не в Windows), поскольку 64-битное адресное пространство гораздо более разреженное.
Что касается моих оптимизаций GC (я - Дэвид Симча, о которых упоминает CyberShadow), то было две партии. Один в течение> 6 месяцев и не вызвал никаких проблем. Другой до сих пор рассматривается как запрос на извлечение и еще не находится в главном дереве druntime. Это, вероятно, не проблема.
В краткосрочной перспективе решение состоит в том, чтобы вручную освободить эти огромные блоки. В долгосрочной перспективе нам нужно добавить точное сканирование, хотя бы для кучи. (Точное сканирование стека является гораздо более сложной проблемой.) Я написал патч, чтобы сделать это пару лет назад, но он был отклонен, потому что он основывался на шаблонах и оценке функции времени компиляции для генерации информации о смещении указателя для каждого типа данных. Надеемся, что эта информация будет в конечном итоге сгенерирована непосредственно компилятором, и я смогу заново создать свой точный патч для сканирования кучи для сборщика мусора.