Здравствуйте.
В рамках одного эксперимента нуждаюсь в готовой реализации однопоточной (то есть без синхронизации) куче, не заточенной под объекты какого-то определенного размера, но при этом разумно оптимизированной по скорости. Понятно, что можно и самому написать, но зачем тратить время на велосипед? Всё что надо, чтобы делала malloc, free, и, по необходимости, лезла в физическую кучу за новым куском памяти. Буду благодарен за любую наводку.
Здравствуйте, Went, Вы писали:
W>Здравствуйте. W>В рамках одного эксперимента нуждаюсь в готовой реализации однопоточной (то есть без синхронизации) куче, не заточенной под объекты какого-то определенного размера, но при этом разумно оптимизированной по скорости. Понятно, что можно и самому написать, но зачем тратить время на велосипед? Всё что надо, чтобы делала malloc, free, и, по необходимости, лезла в физическую кучу за новым куском памяти. Буду благодарен за любую наводку.
Здравствуйте, Videoman, Вы писали:
V>Ну если прям так абстрактно стоит вопрос, просто эксперимент, то в С++17 есть std::pmr::unsynchronized_pool_resource
Спасибо, оно! Жаль у меня 14-ый стандарт, но, можно, в конце концов, просто скопипастить, наверное. А почему вы написали "ну раз просто эксперимент". Для практического применения не подходит?
Здравствуйте, Went, Вы писали:
W>Здравствуйте. W>В рамках одного эксперимента нуждаюсь в готовой реализации однопоточной (то есть без синхронизации) куче, не заточенной под объекты какого-то определенного размера, но при этом разумно оптимизированной по скорости. Понятно, что можно и самому написать, но зачем тратить время на велосипед? Всё что надо, чтобы делала malloc, free, и, по необходимости, лезла в физическую кучу за новым куском памяти. Буду благодарен за любую наводку.
Выше предлагали посмотреть unsynchronized_pool_resource.. Когда то давным давно делал подобную штуку для своих целей, отличия от unsynchronized_pool_resource примерно такие:
1. при освобождении памяти она возвращается в систему (в unsynchronized_pool_resource нет)
2. для освобождения нужно передать только указатель на блок памяти (в unsynchronized_pool_resource надо передать указатель + размер/выравниваение)
3. размер выделяемого блока можно задавать не только в рантайме, но и в compile time, это ускоряет выделение (в unsynchronized_pool_resource — только в рантайм)
4. некоторые арифметические моменты упразднены в силу структуры лайаута низлежащей памяти, что экономит некоторое количество вычислений (в unsynchronized_pool_resource такая арифметика делается в рантайме)
5. разбивка на пулы линейная а не геометрическая, это уменьшает перерасход памяти (в unsynchronized_pool_resource геометрическая)
6. (это скорее минус) адресное пространство под кучу выделяется целиком и сразу (иногда это приводит к проблемам с valgrind, с дампилкой gdb/gcore)
7. (это скорее минус) на 32бит-платформе не вполне эффективно, так как заранее забирает себе много адресного пространства и остальным не хватает. А вот на 64бит — в самый раз
8. (это скорее минус) в имеющемся виде вряд ли будет работать под виндой, там сейчас используется posix mmap/mptotect (но нет противопоказаний переписать на VirtualAlloc, есть работающий пример в другом проекте, если интересно)
Здравствуйте, Went, Вы писали:
W>Здравствуйте, Videoman, Вы писали:
W>Спасибо, оно! Жаль у меня 14-ый стандарт, но, можно, в конце концов, просто скопипастить, наверное. А почему вы написали "ну раз просто эксперимент". Для практического применения не подходит?
Подходит отлично, если нет никаких особенных требований и в среднем будет всех устраивать, как и всё в STL. Просто я уверен, что если прям очень нужна скорость или минимальность по памяти, то можно сделать оптимальнее.
Здравствуйте, Went, Вы писали:
W>В рамках одного эксперимента нуждаюсь в готовой реализации однопоточной (то есть без синхронизации) куче, не заточенной под объекты какого-то определенного размера, но при этом разумно оптимизированной по скорости. Понятно, что можно и самому написать, но зачем тратить время на велосипед? Всё что надо, чтобы делала malloc, free, и, по необходимости, лезла в физическую кучу за новым куском памяти. Буду благодарен за любую наводку.
Если строго под Windows, то можно попробовать HeapCreate с флагом HEAP_NO_SERIALIZE и далее HeapAlloc/HeapFree/HeapDestroy.
Через этот API работает стандартный аллокатор в MS C/C++ Compiler, т.е. можно ожидать вполне адекватную производительность.
Здравствуйте, okman, Вы писали:
O>Здравствуйте, Went, Вы писали:
W>>В рамках одного эксперимента нуждаюсь в готовой реализации однопоточной (то есть без синхронизации) куче, не заточенной под объекты какого-то определенного размера, но при этом разумно оптимизированной по скорости. Понятно, что можно и самому написать, но зачем тратить время на велосипед? Всё что надо, чтобы делала malloc, free, и, по необходимости, лезла в физическую кучу за новым куском памяти. Буду благодарен за любую наводку.
O>Если строго под Windows, то можно попробовать HeapCreate с флагом HEAP_NO_SERIALIZE и далее HeapAlloc/HeapFree/HeapDestroy. O>Через этот API работает стандартный аллокатор в MS C/C++ Compiler, т.е. можно ожидать вполне адекватную производительность.
Да, я попробовал, но был неприятно удивлён производительностью, которая значительно уступала стандартному malloc-free. Я так и не понял, почему. Возможно, "неправильно готовил".