712 lines
16 KiB
Go
712 lines
16 KiB
Go
package pipelinedb
|
||
|
||
import (
|
||
"encoding/binary"
|
||
"errors"
|
||
"os"
|
||
"sort"
|
||
"testing"
|
||
)
|
||
|
||
// TestIndexEntry 测试索引条目的基本功能
|
||
func TestIndexEntry(t *testing.T) {
|
||
entry1 := IndexEntry{ID: 100, PageNo: 5, SlotNo: 10}
|
||
entry2 := IndexEntry{ID: 200, PageNo: 8, SlotNo: 15}
|
||
entry3 := IndexEntry{ID: 100, PageNo: 6, SlotNo: 12} // 相同ID,不同位置
|
||
|
||
// 测试Less方法
|
||
if !entry1.Less(entry2) {
|
||
t.Error("entry1 should be less than entry2")
|
||
}
|
||
|
||
if entry2.Less(entry1) {
|
||
t.Error("entry2 should not be less than entry1")
|
||
}
|
||
|
||
if entry1.Less(entry3) || entry3.Less(entry1) {
|
||
t.Error("entries with same ID should be equal")
|
||
}
|
||
}
|
||
|
||
// TestNewGroupIndex 测试组索引的创建
|
||
func TestNewGroupIndex(t *testing.T) {
|
||
groupName := "test_group"
|
||
idx := NewGroupIndex(groupName)
|
||
|
||
if idx == nil {
|
||
t.Fatal("NewGroupIndex returned nil")
|
||
}
|
||
|
||
if idx.name != groupName {
|
||
t.Errorf("index name = %s, want %s", idx.name, groupName)
|
||
}
|
||
|
||
if idx.Count() != 0 {
|
||
t.Errorf("initial count = %d, want 0", idx.Count())
|
||
}
|
||
|
||
if idx.tree == nil {
|
||
t.Error("B+Tree not initialized")
|
||
}
|
||
}
|
||
|
||
// TestTableIndexInsert 测试索引插入操作
|
||
func TestTableIndexInsert(t *testing.T) {
|
||
idx := NewGroupIndex("test")
|
||
|
||
// 插入一些条目
|
||
testData := []struct {
|
||
id int64
|
||
pageNo uint16
|
||
slotNo uint16
|
||
}{
|
||
{100, 1, 5},
|
||
{200, 2, 10},
|
||
{150, 1, 8},
|
||
{300, 3, 2},
|
||
}
|
||
|
||
for _, data := range testData {
|
||
idx.Insert(data.id, data.pageNo, data.slotNo)
|
||
}
|
||
|
||
// 验证索引大小
|
||
if idx.Count() != len(testData) {
|
||
t.Errorf("count after inserts = %d, want %d", idx.Count(), len(testData))
|
||
}
|
||
|
||
// 验证每个条目都能找到
|
||
for _, data := range testData {
|
||
pageNo, slotNo, found := idx.Get(data.id)
|
||
if !found {
|
||
t.Errorf("entry with ID %d not found", data.id)
|
||
continue
|
||
}
|
||
if pageNo != data.pageNo || slotNo != data.slotNo {
|
||
t.Errorf("entry %d: got (%d, %d), want (%d, %d)",
|
||
data.id, pageNo, slotNo, data.pageNo, data.slotNo)
|
||
}
|
||
}
|
||
}
|
||
|
||
// TestTableIndexInsertUpdate 测试插入时的更新操作
|
||
func TestTableIndexInsertUpdate(t *testing.T) {
|
||
idx := NewGroupIndex("test")
|
||
|
||
id := int64(100)
|
||
|
||
// 首次插入
|
||
idx.Insert(id, 1, 5)
|
||
|
||
pageNo, slotNo, found := idx.Get(id)
|
||
if !found || pageNo != 1 || slotNo != 5 {
|
||
t.Errorf("first insert: got (%d, %d, %t), want (1, 5, true)", pageNo, slotNo, found)
|
||
}
|
||
|
||
// 更新同一ID的位置
|
||
idx.Insert(id, 2, 10)
|
||
|
||
pageNo, slotNo, found = idx.Get(id)
|
||
if !found || pageNo != 2 || slotNo != 10 {
|
||
t.Errorf("after update: got (%d, %d, %t), want (2, 10, true)", pageNo, slotNo, found)
|
||
}
|
||
|
||
// 验证索引大小没有增加
|
||
if idx.Count() != 1 {
|
||
t.Errorf("count after update = %d, want 1", idx.Count())
|
||
}
|
||
}
|
||
|
||
// TestTableIndexGet 测试索引查找操作
|
||
func TestTableIndexGet(t *testing.T) {
|
||
idx := NewGroupIndex("test")
|
||
|
||
// 插入测试数据
|
||
idx.Insert(100, 1, 5)
|
||
idx.Insert(200, 2, 10)
|
||
idx.Insert(300, 3, 15)
|
||
|
||
// 测试存在的条目
|
||
pageNo, slotNo, found := idx.Get(200)
|
||
if !found || pageNo != 2 || slotNo != 10 {
|
||
t.Errorf("Get(200) = (%d, %d, %t), want (2, 10, true)", pageNo, slotNo, found)
|
||
}
|
||
|
||
// 测试不存在的条目
|
||
pageNo, slotNo, found = idx.Get(999)
|
||
if found || pageNo != 0 || slotNo != 0 {
|
||
t.Errorf("Get(999) = (%d, %d, %t), want (0, 0, false)", pageNo, slotNo, found)
|
||
}
|
||
}
|
||
|
||
// TestTableIndexDelete 测试索引删除操作
|
||
func TestTableIndexDelete(t *testing.T) {
|
||
idx := NewGroupIndex("test")
|
||
|
||
// 插入测试数据
|
||
testIDs := []int64{100, 200, 300, 400}
|
||
for i, id := range testIDs {
|
||
idx.Insert(id, uint16(i+1), uint16(i*5))
|
||
}
|
||
|
||
initialCount := idx.Count()
|
||
|
||
// 删除存在的条目
|
||
deleted := idx.Delete(200)
|
||
if !deleted {
|
||
t.Error("Delete(200) should return true")
|
||
}
|
||
|
||
// 验证条目被删除
|
||
_, _, found := idx.Get(200)
|
||
if found {
|
||
t.Error("deleted entry should not be found")
|
||
}
|
||
|
||
// 验证索引大小减少
|
||
if idx.Count() != initialCount-1 {
|
||
t.Errorf("count after delete = %d, want %d", idx.Count(), initialCount-1)
|
||
}
|
||
|
||
// 删除不存在的条目
|
||
deleted = idx.Delete(999)
|
||
if deleted {
|
||
t.Error("Delete(999) should return false")
|
||
}
|
||
|
||
// 验证索引大小没有变化
|
||
if idx.Count() != initialCount-1 {
|
||
t.Errorf("count after deleting non-existent = %d, want %d", idx.Count(), initialCount-1)
|
||
}
|
||
|
||
// 验证其他条目仍然存在
|
||
for _, id := range []int64{100, 300, 400} {
|
||
_, _, found := idx.Get(id)
|
||
if !found {
|
||
t.Errorf("entry %d should still exist", id)
|
||
}
|
||
}
|
||
}
|
||
|
||
// TestTableIndexRange 测试范围查询
|
||
func TestTableIndexRange(t *testing.T) {
|
||
idx := NewGroupIndex("test")
|
||
|
||
// 插入测试数据(乱序插入)
|
||
testData := []struct {
|
||
id int64
|
||
pageNo uint16
|
||
slotNo uint16
|
||
}{
|
||
{300, 3, 15},
|
||
{100, 1, 5},
|
||
{500, 5, 25},
|
||
{200, 2, 10},
|
||
{400, 4, 20},
|
||
}
|
||
|
||
for _, data := range testData {
|
||
idx.Insert(data.id, data.pageNo, data.slotNo)
|
||
}
|
||
|
||
// 测试范围查询 [200, 400]
|
||
var results []int64
|
||
idx.Range(200, 400, func(id int64, pageNo, slotNo uint16) bool {
|
||
results = append(results, id)
|
||
return true // 继续遍历
|
||
})
|
||
|
||
// 验证结果按ID升序排列
|
||
expectedIDs := []int64{200, 300, 400}
|
||
if len(results) != len(expectedIDs) {
|
||
t.Errorf("range query returned %d results, want %d", len(results), len(expectedIDs))
|
||
t.Errorf("actual results: %v", results)
|
||
}
|
||
|
||
for i, expected := range expectedIDs {
|
||
if i >= len(results) || results[i] != expected {
|
||
t.Errorf("result[%d] = %d, want %d", i, results[i], expected)
|
||
}
|
||
}
|
||
|
||
// 测试提前终止的范围查询
|
||
results = nil
|
||
count := 0
|
||
idx.Range(100, 500, func(id int64, pageNo, slotNo uint16) bool {
|
||
results = append(results, id)
|
||
count++
|
||
return count < 2 // 只处理前2个
|
||
})
|
||
|
||
if len(results) != 2 {
|
||
t.Errorf("early termination returned %d results, want 2", len(results))
|
||
}
|
||
|
||
if results[0] != 100 || results[1] != 200 {
|
||
t.Errorf("early termination results = %v, want [100, 200]", results)
|
||
}
|
||
}
|
||
|
||
// TestTableIndexRangeEmpty 测试空范围查询
|
||
func TestTableIndexRangeEmpty(t *testing.T) {
|
||
idx := NewGroupIndex("test")
|
||
|
||
// 插入一些数据
|
||
idx.Insert(100, 1, 5)
|
||
idx.Insert(300, 3, 15)
|
||
|
||
// 查询不存在的范围
|
||
var results []int64
|
||
idx.Range(150, 250, func(id int64, pageNo, slotNo uint16) bool {
|
||
results = append(results, id)
|
||
return true
|
||
})
|
||
|
||
if len(results) != 0 {
|
||
t.Errorf("empty range query returned %d results, want 0", len(results))
|
||
}
|
||
}
|
||
|
||
// TestTableIndexClear 测试清空索引
|
||
func TestTableIndexClear(t *testing.T) {
|
||
idx := NewGroupIndex("test")
|
||
|
||
// 插入一些数据
|
||
for i := int64(1); i <= 10; i++ {
|
||
idx.Insert(i, uint16(i), uint16(i*2))
|
||
}
|
||
|
||
// 验证数据存在
|
||
if idx.Count() != 10 {
|
||
t.Errorf("count before clear = %d, want 10", idx.Count())
|
||
}
|
||
|
||
// 清空索引
|
||
idx.Clear()
|
||
|
||
// 验证索引被清空
|
||
if idx.Count() != 0 {
|
||
t.Errorf("count after clear = %d, want 0", idx.Count())
|
||
}
|
||
|
||
// 验证数据不再存在
|
||
_, _, found := idx.Get(5)
|
||
if found {
|
||
t.Error("data should not exist after clear")
|
||
}
|
||
|
||
// 验证可以重新插入数据
|
||
idx.Insert(100, 1, 5)
|
||
if idx.Count() != 1 {
|
||
t.Errorf("count after re-insert = %d, want 1", idx.Count())
|
||
}
|
||
}
|
||
|
||
// TestNewIndexManager 测试索引管理器的创建
|
||
func TestNewIndexManager(t *testing.T) {
|
||
im := NewIndexManager()
|
||
|
||
if im == nil {
|
||
t.Fatal("NewIndexManager returned nil")
|
||
}
|
||
|
||
if im.indexes == nil {
|
||
t.Error("indexes map not initialized")
|
||
}
|
||
|
||
// 验证初始状态
|
||
stats := im.GetStats()
|
||
if len(stats) != 0 {
|
||
t.Errorf("initial stats length = %d, want 0", len(stats))
|
||
}
|
||
}
|
||
|
||
// TestIndexManagerGetOrCreateIndex 测试获取或创建索引
|
||
func TestIndexManagerGetOrCreateIndex(t *testing.T) {
|
||
im := NewIndexManager()
|
||
|
||
groupName := "test_group"
|
||
|
||
// 第一次调用应该创建新索引
|
||
idx1 := im.GetOrCreateIndex(groupName)
|
||
if idx1 == nil {
|
||
t.Fatal("GetOrCreateIndex returned nil")
|
||
}
|
||
|
||
if idx1.name != groupName {
|
||
t.Errorf("index name = %s, want %s", idx1.name, groupName)
|
||
}
|
||
|
||
// 第二次调用应该返回相同的索引
|
||
idx2 := im.GetOrCreateIndex(groupName)
|
||
if idx2 != idx1 {
|
||
t.Error("GetOrCreateIndex should return the same index instance")
|
||
}
|
||
|
||
// 验证统计信息
|
||
stats := im.GetStats()
|
||
if len(stats) != 1 {
|
||
t.Errorf("stats length = %d, want 1", len(stats))
|
||
}
|
||
|
||
if stats[groupName] != 0 {
|
||
t.Errorf("stats[%s] = %d, want 0", groupName, stats[groupName])
|
||
}
|
||
}
|
||
|
||
// TestIndexManagerGetIndex 测试获取索引
|
||
func TestIndexManagerGetIndex(t *testing.T) {
|
||
im := NewIndexManager()
|
||
|
||
groupName := "test_group"
|
||
|
||
// 获取不存在的索引
|
||
idx, exists := im.GetIndex(groupName)
|
||
if exists || idx != nil {
|
||
t.Error("GetIndex should return (nil, false) for non-existent index")
|
||
}
|
||
|
||
// 创建索引
|
||
createdIdx := im.GetOrCreateIndex(groupName)
|
||
|
||
// 获取存在的索引
|
||
idx, exists = im.GetIndex(groupName)
|
||
if !exists || idx != createdIdx {
|
||
t.Error("GetIndex should return the created index")
|
||
}
|
||
}
|
||
|
||
// TestIndexManagerDropIndex 测试删除索引
|
||
func TestIndexManagerDropIndex(t *testing.T) {
|
||
im := NewIndexManager()
|
||
|
||
groupName := "test_group"
|
||
|
||
// 创建索引并添加数据
|
||
idx := im.GetOrCreateIndex(groupName)
|
||
idx.Insert(100, 1, 5)
|
||
idx.Insert(200, 2, 10)
|
||
|
||
// 验证索引存在且有数据
|
||
if idx.Count() != 2 {
|
||
t.Errorf("index count = %d, want 2", idx.Count())
|
||
}
|
||
|
||
stats := im.GetStats()
|
||
if stats[groupName] != 2 {
|
||
t.Errorf("stats[%s] = %d, want 2", groupName, stats[groupName])
|
||
}
|
||
|
||
// 删除索引
|
||
im.DropIndex(groupName)
|
||
|
||
// 验证索引被删除
|
||
_, exists := im.GetIndex(groupName)
|
||
if exists {
|
||
t.Error("index should not exist after drop")
|
||
}
|
||
|
||
// 验证统计信息更新
|
||
stats = im.GetStats()
|
||
if len(stats) != 0 {
|
||
t.Errorf("stats length after drop = %d, want 0", len(stats))
|
||
}
|
||
|
||
// 删除不存在的索引应该是安全的
|
||
im.DropIndex("non_existent")
|
||
}
|
||
|
||
// TestIndexManagerGetStats 测试获取统计信息
|
||
func TestIndexManagerGetStats(t *testing.T) {
|
||
im := NewIndexManager()
|
||
|
||
// 创建多个索引并添加不同数量的数据
|
||
groups := map[string]int{
|
||
"group1": 5,
|
||
"group2": 10,
|
||
"group3": 3,
|
||
}
|
||
|
||
for groupName, count := range groups {
|
||
idx := im.GetOrCreateIndex(groupName)
|
||
for i := 0; i < count; i++ {
|
||
idx.Insert(int64(i), uint16(i), uint16(i*2))
|
||
}
|
||
}
|
||
|
||
// 获取统计信息
|
||
stats := im.GetStats()
|
||
|
||
// 验证统计信息
|
||
if len(stats) != len(groups) {
|
||
t.Errorf("stats length = %d, want %d", len(stats), len(groups))
|
||
}
|
||
|
||
for groupName, expectedCount := range groups {
|
||
if stats[groupName] != expectedCount {
|
||
t.Errorf("stats[%s] = %d, want %d", groupName, stats[groupName], expectedCount)
|
||
}
|
||
}
|
||
}
|
||
|
||
// MockPipelineDB 用于测试RebuildIndex的模拟数据库
|
||
type MockPipelineDB struct {
|
||
pages map[uint16]*MockPage
|
||
}
|
||
|
||
type MockPage struct {
|
||
data []byte
|
||
nextPageNo uint16
|
||
slots []uint16
|
||
}
|
||
|
||
func (p *MockPage) slotArray() []uint16 {
|
||
return p.slots
|
||
}
|
||
|
||
func (p *MockPage) nextPage() uint16 {
|
||
return p.nextPageNo
|
||
}
|
||
|
||
func NewMockPipelineDB() *MockPipelineDB {
|
||
return &MockPipelineDB{
|
||
pages: make(map[uint16]*MockPage),
|
||
}
|
||
}
|
||
|
||
func (db *MockPipelineDB) readPage(pageNo uint16) (*MockPage, error) {
|
||
if page, exists := db.pages[pageNo]; exists {
|
||
return page, nil
|
||
}
|
||
return nil, errors.New("page not found")
|
||
}
|
||
|
||
func (db *MockPipelineDB) addPage(pageNo uint16, nextPage uint16, records []struct {
|
||
id int64
|
||
offset uint16
|
||
}) {
|
||
page := &MockPage{
|
||
data: make([]byte, PageSize),
|
||
nextPageNo: nextPage,
|
||
slots: make([]uint16, len(records)),
|
||
}
|
||
|
||
for i, record := range records {
|
||
// 将ID写入指定偏移位置
|
||
binary.LittleEndian.PutUint64(page.data[record.offset:], uint64(record.id))
|
||
page.slots[i] = record.offset
|
||
}
|
||
|
||
db.pages[pageNo] = page
|
||
}
|
||
|
||
// TestRebuildIndex 测试索引重建
|
||
func TestRebuildIndex(t *testing.T) {
|
||
// 创建一个临时的PipelineDB实例用于测试
|
||
tmpFile, err := os.CreateTemp("", "rebuild_test_*.db")
|
||
if err != nil {
|
||
t.Fatalf("failed to create temp file: %v", err)
|
||
}
|
||
defer os.Remove(tmpFile.Name())
|
||
tmpFile.Close()
|
||
|
||
config := &Config{CacheSize: 10}
|
||
pdb, err := Open(Options{
|
||
Filename: tmpFile.Name(),
|
||
Config: config,
|
||
})
|
||
if err != nil {
|
||
t.Fatalf("Open failed: %v", err)
|
||
}
|
||
defer pdb.Stop()
|
||
|
||
// 先添加一些测试数据
|
||
testData := [][]byte{
|
||
[]byte("test data 1"),
|
||
[]byte("test data 2"),
|
||
[]byte("test data 3"),
|
||
}
|
||
|
||
var recordIDs []int64
|
||
for _, data := range testData {
|
||
recordID, err := pdb.AcceptData("test_group", data, `{"test": true}`)
|
||
if err != nil {
|
||
t.Fatalf("AcceptData failed: %v", err)
|
||
}
|
||
recordIDs = append(recordIDs, recordID)
|
||
}
|
||
|
||
// 重建索引
|
||
idx, err := pdb.RebuildIndex("test_group", 1)
|
||
if err != nil {
|
||
t.Errorf("RebuildIndex returned error: %v", err)
|
||
}
|
||
|
||
if idx == nil {
|
||
t.Fatal("RebuildIndex returned nil index")
|
||
}
|
||
|
||
// 验证索引包含所有记录
|
||
if idx.Count() != len(recordIDs) {
|
||
t.Errorf("rebuilt index count = %d, want %d", idx.Count(), len(recordIDs))
|
||
}
|
||
|
||
// 验证每个记录都能在索引中找到
|
||
for _, recordID := range recordIDs {
|
||
_, _, found := idx.Get(recordID)
|
||
if !found {
|
||
t.Errorf("record %d not found in rebuilt index", recordID)
|
||
}
|
||
}
|
||
}
|
||
|
||
// TestIndexLargeDataset 测试大数据集的索引操作
|
||
func TestIndexLargeDataset(t *testing.T) {
|
||
idx := NewGroupIndex("large_test")
|
||
|
||
const numRecords = 10000
|
||
|
||
// 插入大量记录
|
||
for i := int64(1); i <= numRecords; i++ {
|
||
idx.Insert(i, uint16(i%1000), uint16(i%100))
|
||
}
|
||
|
||
// 验证记录数量
|
||
if idx.Count() != numRecords {
|
||
t.Errorf("count = %d, want %d", idx.Count(), numRecords)
|
||
}
|
||
|
||
// 随机验证一些记录
|
||
testIDs := []int64{1, 100, 1000, 5000, 9999, 10000}
|
||
for _, id := range testIDs {
|
||
_, _, found := idx.Get(id)
|
||
if !found {
|
||
t.Errorf("record %d not found", id)
|
||
}
|
||
}
|
||
|
||
// 测试范围查询
|
||
var rangeResults []int64
|
||
idx.Range(5000, 5010, func(id int64, pageNo, slotNo uint16) bool {
|
||
rangeResults = append(rangeResults, id)
|
||
return true
|
||
})
|
||
|
||
expectedRange := []int64{5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010}
|
||
if len(rangeResults) != len(expectedRange) {
|
||
t.Errorf("range query returned %d results, want %d", len(rangeResults), len(expectedRange))
|
||
}
|
||
|
||
// 删除一些记录
|
||
for i := int64(1000); i <= 2000; i++ {
|
||
idx.Delete(i)
|
||
}
|
||
|
||
// 验证删除后的数量
|
||
expectedCount := numRecords - 1001 // 删除了1001个记录(1000到2000,包含两端)
|
||
if idx.Count() != expectedCount {
|
||
t.Errorf("count after deletion = %d, want %d", idx.Count(), expectedCount)
|
||
}
|
||
}
|
||
|
||
// TestIndexOrdering 测试索引的有序性
|
||
func TestIndexOrdering(t *testing.T) {
|
||
idx := NewGroupIndex("order_test")
|
||
|
||
// 乱序插入数据
|
||
ids := []int64{500, 100, 300, 200, 400, 600, 150, 350}
|
||
for _, id := range ids {
|
||
idx.Insert(id, uint16(id/100), uint16(id%100))
|
||
}
|
||
|
||
// 范围查询应该返回有序结果
|
||
var results []int64
|
||
idx.Range(0, 1000, func(id int64, pageNo, slotNo uint16) bool {
|
||
results = append(results, id)
|
||
return true
|
||
})
|
||
|
||
// 验证结果是有序的
|
||
if !sort.SliceIsSorted(results, func(i, j int) bool {
|
||
return results[i] < results[j]
|
||
}) {
|
||
t.Errorf("range query results are not sorted: %v", results)
|
||
}
|
||
|
||
// 验证所有ID都存在
|
||
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
|
||
if len(results) != len(ids) {
|
||
t.Errorf("result count = %d, want %d", len(results), len(ids))
|
||
}
|
||
|
||
for i, expected := range ids {
|
||
if i >= len(results) || results[i] != expected {
|
||
t.Errorf("result[%d] = %d, want %d", i, results[i], expected)
|
||
}
|
||
}
|
||
}
|
||
|
||
// BenchmarkTableIndexInsert 性能测试:索引插入
|
||
func BenchmarkTableIndexInsert(b *testing.B) {
|
||
idx := NewGroupIndex("bench_test")
|
||
|
||
b.ResetTimer()
|
||
|
||
for i := 0; i < b.N; i++ {
|
||
idx.Insert(int64(i), uint16(i%1000), uint16(i%100))
|
||
}
|
||
}
|
||
|
||
// BenchmarkTableIndexGet 性能测试:索引查找
|
||
func BenchmarkTableIndexGet(b *testing.B) {
|
||
idx := NewGroupIndex("bench_test")
|
||
|
||
// 预填充数据
|
||
for i := 0; i < 100000; i++ {
|
||
idx.Insert(int64(i), uint16(i%1000), uint16(i%100))
|
||
}
|
||
|
||
b.ResetTimer()
|
||
|
||
for i := 0; i < b.N; i++ {
|
||
idx.Get(int64(i % 100000))
|
||
}
|
||
}
|
||
|
||
// BenchmarkTableIndexRange 性能测试:范围查询
|
||
func BenchmarkTableIndexRange(b *testing.B) {
|
||
idx := NewGroupIndex("bench_test")
|
||
|
||
// 预填充数据
|
||
for i := 0; i < 100000; i++ {
|
||
idx.Insert(int64(i), uint16(i%1000), uint16(i%100))
|
||
}
|
||
|
||
b.ResetTimer()
|
||
|
||
for i := 0; i < b.N; i++ {
|
||
start := int64(i % 90000)
|
||
end := start + 100
|
||
idx.Range(start, end, func(id int64, pageNo, slotNo uint16) bool {
|
||
return true
|
||
})
|
||
}
|
||
}
|
||
|
||
// BenchmarkIndexManagerOperations 性能测试:索引管理器操作
|
||
func BenchmarkIndexManagerOperations(b *testing.B) {
|
||
im := NewIndexManager()
|
||
|
||
b.ResetTimer()
|
||
|
||
for i := 0; i < b.N; i++ {
|
||
groupName := "group_" + string(rune('A'+i%26))
|
||
idx := im.GetOrCreateIndex(groupName)
|
||
idx.Insert(int64(i), uint16(i%1000), uint16(i%100))
|
||
|
||
if i%1000 == 0 {
|
||
im.GetStats()
|
||
}
|
||
}
|
||
}
|