#include "size_map.h" #include "shm_helper.h" #include "shm_manager.h" #include "shm_config.h" namespace bg { namespace detail { bool SizeMap::Init() { // ·ÖÒ³ size_t size = 8; size_t class_cnt = 0; size_t index_total = 1; size_t index = 0; do { size_t alig_size = bg::detail::SizeMap::CalcAlignment(size); if(size) { class_cnt = CLASS_TOTAL_BYTES / size; if(class_cnt) { class_cnt = std::min(MAX_CLASSS, class_cnt); class_cnt >>= 2; } } size_t alig_page_byte = 0LL; do { for(alig_page_byte += PAGE_BYTES; alig_page_byte % size > alig_page_byte >> 3; alig_page_byte += PAGE_BYTES); } while(alig_page_byte / size < class_cnt); size_t page_cnt = BYTES_TO_PAGES(alig_page_byte); if(index_total > 1 && page_cnt == m_class_to_pages[index_total - 1] && alig_page_byte / size == alig_page_byte / m_class_to_size[index_total - 1]) { m_class_to_size[index_total - 1] = size; } else { m_class_to_pages[index_total] = page_cnt; m_class_to_size[index_total] = size; index_total++; } size += alig_size; } while(size <= CLASS_MAX_BYTES); if(index_total > CLASS_MAX_COUNT) { SHM_WARN("too many size classes, found: %u, max: %u", index_total, CLASS_MAX_COUNT); } else { if(index_total > 1u) { size = 0; for(char i = 1; i < index_total; ++i) { for(size_t j = m_class_to_size[i]; j >= size; size += SMALL_CALIGNMENT) { if(size <= BYTES_COMP_VALUE) { m_index_to_class[SMALL_BYTES_TO_INDEX(size)] = i; } else { m_index_to_class[BIG_BYTES_TO_INDEX(size)] = i; } } } } size = 0; while(true) { if(size <= BYTES_COMP_VALUE) { index = m_index_to_class[SMALL_BYTES_TO_INDEX(size)]; } else { index = m_index_to_class[BIG_BYTES_TO_INDEX(size)]; } if(index >= index_total) { goto FAIL; } size_t value = this->m_class_to_size[index]; if(index > 1) { if(m_class_to_size[index - 1] >= size) { SHM_WARN("size class too large, class: %zu, size: %zu", index, size); return false; } } if(!value) { SHM_WARN("bad class: %zu, size: %zu", index, size); return false; } if(size > BYTES_COMP_VALUE) { size += SMALL_BYTES_TO_INDEX(BYTES_COMP_VALUE); if(size <= CLASS_MAX_BYTES) { continue; } return true; } size += SMALL_CALIGNMENT; } } FAIL: SHM_WARN("bad size class, class: %u, size: %lu", index, size); return false; } size_t SizeMap::CalcAlignment(size_t bytes) { size_t result; // rax char bit{}; result = PAGE_BYTES; if(bytes < (PAGE_BYTES << 4)) { if(bytes <= 0x7F) { return (-(int64_t)(bytes < 0x10) & 0xFFFFFFFFFFFFFFF8LL) + 16; } else { for(int i = 16; i >= 1; i >>= 1) { size_t temp = bytes >> i; if(temp) { bit += i; bytes = temp; } } result = (1ul << bit) >> 3; return result; } } return result; } } }