Обновить

Комментарии 4

Да, тут вся соль в многопоточности. Как локально кэшировать выделяемые объекты и как затем возвращать свободные - в глобальный пул. Лучше, чем это делают jemalloc и tcmalloc.

Пул используется более широко: когда создать объект дорого и проще использовать освободившийся. Например, сетевые соединения.

Почему вы взяли для примера критерий экономии памяти не понятно.

Хорошая реализация для базового случая – особенно стек индексов вместо linked list: он лучше дружит с кэшом при одном потоке. Кстати, к разделу про потокобезопасность стоит добавить ещё один сценарий: даже с мьютексом пул может деградировать на SMP-системах из-за ложного разделения кэша (false sharing). Если поток A держит сегмент #5, а поток B – сегмент #6, и оба помещаются на одну кэш-линию (64 байта на x86), каждая запись одного потока инвалидирует строку у другого. Лечится выравниванием сегментов до размера кэш-линии – с небольшим компромиссом по памяти.

пул классно, но с потоками или каналами всё становится интереснее, например, общение через каналы по состояниям с общим владением, тогда кусочки опять откуда брать придётся ), чтобы сгенерировать, а как паттерн да удобно...

я про ситуацию когда этот паттерн на синхро-уровне по владению, тогда в этих красках кусочки приходящии от генерации тоже должны крутиться(наверно из пула тоже) ). Я понимаю что описываю словами, но в коде гемор, получается 2-3 пула одного и тоже, одно на владение между каналами, другое на паралельный запуск генерации, тогда получается на такую систему 2 версии одного и того же)

Скрытый текст
pub struct ChunkTaskResult {
    pub pos: Vec3i,
    pub task_type: TaskType,
    pub chunk_data: ChunkDataTask,
    // pub light_data: Option<Arc<[u8; 4096]>>,
    pub vertices: Option<Vec<VoxelVertex>>,
    pub indices: Option<Vec<u32>>,
    pub revision: u32, // К какой версии данных относится этот меш
    // Делаем Option, так как соседи нужны ТОЛЬКО для TaskType::GenerateMesh
    pub neighbors: Option<MeshNeighbors>,
}
...
#[allow(unused)]
pub struct World {
    pub chunks: HashMap<Vec3i, VoxelChunk>,
    // Приемник результатов мешизации
    cave_noise: Perlin,
    pub loading_queue: HashSet<Vec3i>, // Для GenerateData
    pub meshing_queue: HashSet<Vec3i>, // Для GenerateMesh
    // Канал для получения готовых чанков
    rx_done: Receiver<ChunkTaskResult>,
    // Канал для отправки заданий (если нужно динамически)
    tx_tasks: Sender<ChunkTaskResult>,
    pub allocator: mxg11alc::alloc::Gsa, пул слотов на 258 мебагайт для карточки - синхронизированные куски которыми владеют каналы по отрисовке )
    pub mega_vbo: u32,
    pub mega_ebo: u32,
}
...
и в такой ситуации ворлд каналы в апдейт синхронизируют общее владение
казалось бы ок, но
  fn new() -> Self{
...
        std::thread::spawn(move || {
            while let Ok(task) = rx_tasks.recv() {
                match task.task_type {
                    TaskType::GenerateData =>{
                        //1 (16*4096)
                        let raw_data=generate_c(&task.pos, &seed);
...
                    TaskType::GenerateMesh =>{
                        match task.chunk_data {
                            ChunkDataTask::Full(..)=>{
                                if let Some(nb) = task.neighbors {
                                    //2 а тут либо плохие случаи шихматная доска(либо компромисс 7к каждый на первое время )*16)
                                    let mut vertices = Vec::new();
                                    //3 как выше 7к*16
                                    let mut indices = Vec::new();
                                    build_seamless_mesh(&nb, &mut vertices, &mut indices);
}//fn new Self
...
fn update можно настроить чтобы он брал и чистил, но системе не будет хватать опять тех же пулов чтобы откудато брать пулы на генерацию и создания мешев вообще интересная ситуация )

я пока так оставил(тоесть ЦПУ пула нет просто чищу приходящую в канал память и это не грузит проц на дистанции 16х2х16 чанков(16х16х16 блоков) по горизонтали), 16 потоков держит по синхронизации и не грузит проц)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации