송신에 쓸 버퍼를 할당의 경우 효율성을 위해 메모리 풀을 사용합니다.
그런데 테스트 결과, 메모리 풀에 락을 걸면 속도가 상당히 떨어지더라고요.
뮤텍스를 사용하는 것만으로 기본 할당자(malloc, new)를 사용하는 것보다 속도가 월등히 떨어지다보니
스레드 로컬 풀을 만들고자 했습니다.
그런데 이렇게 하면 메모리 해제의 경우가 곤란했습니다.
할당의 경우는 항상 그 스레드 전용의 메모리 풀에서 하기에 동기화가 필요 없지만,
해제의 경우 다른 스레드에서 일어날 수 있으므로 동기화가 필요했습니다.
이러면 할당에도 동기화가 필요하게 되므로 스레드 로컬의 의미가 없게 됩니다.
그래서 마땅한 방법이 없을까 했는데, 다음과 같은 방법이 떠올랐습니다.
할당은 스레드 로컬 풀에서, 해제된 메모리는 공용의 해제 메모리 보관함에 보관,
그리고 스레드 로컬 풀의 메모리가 부족할 때 메모리 보관함에서 메모리를 꺼내온다.
이러면 빈번한 스레드 잠금을 피할 수 있을지 않을까요?
+ 2016/01/28
할당된 메모리들은 어느 스레드 풀에서 할당 되었는지를 알 수 있도록 정보를 담는 헤더(또는 트레일러)가 필요합니다.
그렇지 않으면 어느 풀에서 할당되었는지 알 수가 없죠.
struct buffer_info
{
std::thread::id thread_id;
void* chunk;
size_t size;
}
하지만 구조체 반환하는 건 기존 void*를 반환하는 메모리 할당 코드와는 다릅니다.
따라서 void*를 반환하되, 헤더에 버퍼에 대한 정보를 담고자 합니다.
[헤더][메모리/* 유저에겐 이 부분을 반환합니다!*/]
그리고 해제의 경우엔
void pool::free(void* chunk)
{
memory_header* header = reinterpret_cast<memory_header*>(chunk) - 1;
//.. 프리 메모리 보관함에 담는다.
// header->thread_id ...
// header->size ..
}
이렇게 해두면 풀에 해제만 해도 메모리가 생성된 풀을 알 수 있겠네요
첫댓글 그렇군요..
후에 tcmalloc과 jemalloc에 관한 글도 읽어봐야겠습니다. 지금 당장 읽으면 그 구현에 생각이 얽매여 어설프게 흉내만 내려고 할 거 같아요. 좋은 정보 감사합니다. ^^