[Improvement] (MG_Util/Misc): Replace byte array with 64-bit bitmap in IndexGenerator.

This commit is contained in:
BZLZHH
2025-07-25 12:40:38 +08:00
parent e79a2fa809
commit 5962499147
2 changed files with 51 additions and 24 deletions
+1 -1
View File
@@ -89,7 +89,7 @@
typedef int android_LogPriority;
inline int __android_log_print(int prio, const char* tag, const char* fmt, ...) { }
inline int __android_log_print(int prio, const char* tag, const char* fmt, ...) { return 0; }
#endif
#include "MG_Util/GLExtensions.h"
+50 -23
View File
@@ -1,7 +1,4 @@
#pragma once
#include <vector>
#include <algorithm>
#include <cstdint>
namespace MobileGL {
template <typename IndexType>
@@ -10,49 +7,79 @@ namespace MobileGL {
explicit IndexGenerator(size_t initial_capacity = 1024, IndexType first_index = 0)
: next_index_(first_index)
{
is_valid_.reserve(initial_capacity);
const size_t words_needed = (initial_capacity + 63) / 64;
is_valid_.resize(words_needed, ~0ull);
freed_indices_.reserve(initial_capacity);
}
void Generate(size_t n, IndexType* indices) {
if (n == 0) return;
size_t from_freed = std::min(n, freed_indices_.size());
for (size_t i = 0; i < from_freed; ++i) {
indices[i] = freed_indices_.back();
freed_indices_.pop_back();
is_valid_[indices[i]] = 1;
if (from_freed > 0) {
std::copy_n(freed_indices_.end() - from_freed, from_freed, indices);
freed_indices_.resize(freed_indices_.size() - from_freed);
for (size_t i = 0; i < from_freed; ++i) {
SetValid(indices[i], true);
}
}
size_t need_new = n - from_freed;
if (need_new > 0) {
size_t required = next_index_ + need_new;
if (required > is_valid_.size()) {
size_t new_cap = std::max(required, is_valid_.size() * 2);
is_valid_.resize(new_cap, 0);
size_t required_index = next_index_ + need_new;
size_t required_words = (required_index + 63) / 64;
if (required_words > is_valid_.size()) {
is_valid_.resize(required_words, ~0ull);
}
for (size_t i = 0; i < need_new; ++i) {
indices[from_freed + i] = next_index_;
is_valid_[next_index_] = 1;
++next_index_;
indices[from_freed + i] = next_index_++;
}
}
}
void Delete(IndexType index) {
if (index < is_valid_.size() && is_valid_[index]) {
is_valid_[index] = 0;
freed_indices_.push_back(index);
SetValid(index, false);
freed_indices_.push_back(index);
if (freed_indices_.size() > 1024 && freed_indices_.size() > next_index_ / 2) {
CompactFreeList();
}
}
bool IsValid(IndexType index) const {
return index < is_valid_.size() && is_valid_[index];
size_t word = index >> 6;
size_t bit = index & 0x3F;
return word < is_valid_.size() && (is_valid_[word] & (1ull << bit));
}
size_t FreeListSize() const { return freed_indices_.size(); }
size_t ActiveCount() const { return next_index_ - freed_indices_.size(); }
private:
inline void SetValid(IndexType index, bool valid) {
size_t word = index >> 6;
uint64_t mask = 1ull << (index & 0x3F);
if (word >= is_valid_.size()) return;
if (valid) {
is_valid_[word] |= mask;
}
else {
is_valid_[word] &= ~mask;
}
}
void CompactFreeList() {
std::sort(freed_indices_.begin(), freed_indices_.end());
auto last = std::unique(freed_indices_.begin(), freed_indices_.end());
freed_indices_.erase(last, freed_indices_.end());
}
private:
IndexType next_index_ = 0;
std::vector<IndexType> freed_indices_;
std::vector<Uint8> is_valid_;
std::vector<IndexType> freed_indices_;
std::vector<Uint64> is_valid_;
};
}
}