diff --git a/src/main/java/com/yomahub/roguemap/RogueMap.java b/src/main/java/com/yomahub/roguemap/RogueMap.java index 6fb32ec..6e95145 100644 --- a/src/main/java/com/yomahub/roguemap/RogueMap.java +++ b/src/main/java/com/yomahub/roguemap/RogueMap.java @@ -49,19 +49,19 @@ private RogueMap(Index index, StorageEngine storage, */ public V put(K key, V value) { if (key == null) { - throw new IllegalArgumentException("键不能为 null"); + throw new IllegalArgumentException("Key cannot be null"); } // 计算所需大小 int valueSize = valueCodec.calculateSize(value); if (valueSize < 0) { - throw new IllegalStateException("无法确定值的大小"); + throw new IllegalStateException("Cannot determine value size"); } // 为值分配内存 - long newAddress = allocator.allocate(valueSize); - if (newAddress == 0) { - throw new OutOfMemoryError("分配 " + valueSize + " 字节失败"); + long address = allocator.allocate(valueSize); + if (address == 0) { + throw new OutOfMemoryError("Failed to allocate " + valueSize + " bytes"); } try { @@ -167,13 +167,12 @@ public boolean isEmpty() { * 移除所有条目 */ public void clear() { - // 遍历所有条目并释放内存 - index.forEach((key, address, size) -> { - allocator.free(address, size); + // 使用新添加的 clear(Consumer) 方法,在清除索引的同时释放堆外内存 + index.clear((address, size) -> { + if (address != 0) { + allocator.free(address, size); + } }); - - // 清空索引 - index.clear(); } /** @@ -333,7 +332,7 @@ public B valueCodec(Codec valueCodec) { */ public B initialCapacity(int initialCapacity) { if (initialCapacity <= 0) { - throw new IllegalArgumentException("initialCapacity 必须为正数"); + throw new IllegalArgumentException("initialCapacity must be positive"); } this.initialCapacity = initialCapacity; return (B) this; @@ -393,7 +392,7 @@ protected Index createIndexFromType(int indexType, Codec keyCodec) { } else if (indexType == 3) { return (Index) new IntPrimitiveIndex(initialCapacity); } - throw new IllegalStateException("未知的索引类型: " + indexType); + throw new IllegalStateException("Unknown index type: " + indexType); } /** @@ -412,7 +411,7 @@ protected Index createNewIndex(Codec keyCodec) { return (Index) new IntPrimitiveIndex(initialCapacity); } else { throw new IllegalStateException( - "原始类型索引仅支持 Long 或 Integer 键,请使用 PrimitiveCodecs.LONG 或 PrimitiveCodecs.INTEGER"); + "Primitive index only supports Long or Integer keys, please use PrimitiveCodecs.LONG or PrimitiveCodecs.INTEGER" ); } } else if (useSegmentedIndex) { return new SegmentedHashIndex<>(keyCodec, segmentCount, initialCapacity); @@ -451,7 +450,7 @@ private MmapBuilder() { */ public MmapBuilder persistent(String filePath) { if (filePath == null || filePath.isEmpty()) { - throw new IllegalArgumentException("文件路径不能为空"); + throw new IllegalArgumentException("File path cannot be empty"); } this.persistentFilePath = filePath; this.isTemporary = false; @@ -478,7 +477,7 @@ public MmapBuilder temporary() { */ public MmapBuilder allocateSize(long size) { if (size <= 0) { - throw new IllegalArgumentException("分配大小必须为正数"); + throw new IllegalArgumentException("Allocate size must be positive"); } this.allocateSize = size; return this; @@ -487,15 +486,15 @@ public MmapBuilder allocateSize(long size) { @Override public RogueMap build() { if (keyCodec == null) { - throw new IllegalStateException("必须设置键编解码器"); + throw new IllegalStateException("Key codec must be set"); } if (valueCodec == null) { - throw new IllegalStateException("必须设置值编解码器"); + throw new IllegalStateException("Value codec must be set"); } // 临时文件模式不需要指定路径 if (!isTemporary && (persistentFilePath == null || persistentFilePath.isEmpty())) { - throw new IllegalStateException("MMAP 模式必须设置文件路径,请使用 persistent(filePath) 或 temporary()"); + throw new IllegalStateException("MMAP mode must set file path, please use persistent(filePath) or temporary()"); } // 创建 MmapAllocator(临时模式会自动生成文件路径) @@ -555,7 +554,7 @@ private OffHeapBuilder() { */ public OffHeapBuilder maxMemory(long maxMemory) { if (maxMemory <= 0) { - throw new IllegalArgumentException("maxMemory 必须为正数"); + throw new IllegalArgumentException("maxMemory must be positive"); } this.maxMemory = maxMemory; return this; @@ -564,10 +563,10 @@ public OffHeapBuilder maxMemory(long maxMemory) { @Override public RogueMap build() { if (keyCodec == null) { - throw new IllegalStateException("必须设置键编解码器"); + throw new IllegalStateException("Key codec must be set"); } if (valueCodec == null) { - throw new IllegalStateException("必须设置值编解码器"); + throw new IllegalStateException("Value codec must be set"); } // 堆外内存模式 diff --git a/src/main/java/com/yomahub/roguemap/func/EntryConsumer.java b/src/main/java/com/yomahub/roguemap/func/EntryConsumer.java new file mode 100644 index 0000000..0ea12b1 --- /dev/null +++ b/src/main/java/com/yomahub/roguemap/func/EntryConsumer.java @@ -0,0 +1,6 @@ +package com.yomahub.roguemap.func; + +@FunctionalInterface +public interface EntryConsumer { + void accept(long address, int size); +} \ No newline at end of file diff --git a/src/main/java/com/yomahub/roguemap/index/HashIndex.java b/src/main/java/com/yomahub/roguemap/index/HashIndex.java index 570e3b5..f08c8cc 100644 --- a/src/main/java/com/yomahub/roguemap/index/HashIndex.java +++ b/src/main/java/com/yomahub/roguemap/index/HashIndex.java @@ -1,5 +1,6 @@ package com.yomahub.roguemap.index; +import com.yomahub.roguemap.func.EntryConsumer; import com.yomahub.roguemap.memory.UnsafeOps; import com.yomahub.roguemap.serialization.Codec; @@ -39,10 +40,10 @@ public HashIndex(Codec keyCodec, int initialCapacity) { @Override public long put(K key, long address, int valueSize) { if (key == null) { - throw new IllegalArgumentException("键不能为 null"); + throw new IllegalArgumentException("Key cannot be null"); } if (address == 0) { - throw new IllegalArgumentException("无效的地址: 0"); + throw new IllegalArgumentException("Invalid address: 0"); } Entry newEntry = new Entry(address, valueSize); @@ -147,8 +148,20 @@ public int size() { @Override public void clear() { - map.clear(); - size.set(0); + clear(null); + } + + @Override + public void clear(EntryConsumer action) { + // 使用迭代器逐个移除,确保原子性和回调执行 + map.forEach((k, v) -> { + if (map.remove(k, v)) { // 原子性移除 + size.decrementAndGet(); + if (action != null) { + action.accept(v.address, v.size); + } + } + }); } @Override @@ -159,7 +172,7 @@ public void close() { @Override public int serializedSize() { if (keyCodec == null) { - throw new UnsupportedOperationException("无法序列化:keyCodec 为 null"); + throw new UnsupportedOperationException("Serialization not supported: keyCodec is null"); } int totalSize = 4; // entry count (4 bytes) @@ -168,7 +181,7 @@ public int serializedSize() { K key = entry.getKey(); int keySize = keyCodec.calculateSize(key); if (keySize < 0) { - throw new IllegalStateException("键的大小不能为负数"); + throw new IllegalStateException("Key size cannot be negative"); } // 4 bytes (key size) + key bytes + 8 bytes (address) + 4 bytes (size) totalSize += 4 + keySize + 8 + 4; @@ -180,7 +193,7 @@ public int serializedSize() { @Override public int serialize(long address) { if (keyCodec == null) { - throw new UnsupportedOperationException("无法序列化:keyCodec 为 null"); + throw new UnsupportedOperationException("Serialization not supported: keyCodec is null"); } long currentAddr = address; @@ -196,7 +209,7 @@ public int serialize(long address) { // 计算键大小并编码 int keySize = keyCodec.calculateSize(key); if (keySize < 0) { - throw new IllegalStateException("键的大小不能为负数"); + throw new IllegalStateException("Key size cannot be negative"); } // 写入 key size @@ -222,7 +235,7 @@ public int serialize(long address) { @Override public void deserialize(long address, int totalSize) { if (keyCodec == null) { - throw new UnsupportedOperationException("无法反序列化:keyCodec 为 null"); + throw new UnsupportedOperationException("Deserialization not supported: keyCodec is null"); } map.clear(); @@ -260,7 +273,7 @@ public void deserialize(long address, int totalSize) { @Override public int serializeWithOffsets(long address, long baseAddress) { if (keyCodec == null) { - throw new UnsupportedOperationException("无法序列化:keyCodec 为 null"); + throw new UnsupportedOperationException("Serialization not supported: keyCodec is null"); } long currentAddr = address; @@ -276,7 +289,7 @@ public int serializeWithOffsets(long address, long baseAddress) { // 计算键大小并编码 int keySize = keyCodec.calculateSize(key); if (keySize < 0) { - throw new IllegalStateException("键的大小不能为负数"); + throw new IllegalStateException("Key size cannot be negative"); } // 写入 key size @@ -303,7 +316,7 @@ public int serializeWithOffsets(long address, long baseAddress) { @Override public void deserializeWithOffsets(long address, int totalSize, long baseAddress) { if (keyCodec == null) { - throw new UnsupportedOperationException("无法反序列化:keyCodec 为 null"); + throw new UnsupportedOperationException("Deserialization not supported: keyCodec is null"); } map.clear(); @@ -341,6 +354,16 @@ public void deserializeWithOffsets(long address, int totalSize, long baseAddress this.size.set(entryCount); } + @Override + public void forEach(EntryConsumer action) { + if (action == null) { + throw new IllegalArgumentException("Action cannot be null"); + } + for (Entry entry : map.values()) { + action.accept(entry.address, entry.size); + } + } + /** * Entry 保存值的内存地址和大小 */ diff --git a/src/main/java/com/yomahub/roguemap/index/Index.java b/src/main/java/com/yomahub/roguemap/index/Index.java index 28bb00e..0633c91 100644 --- a/src/main/java/com/yomahub/roguemap/index/Index.java +++ b/src/main/java/com/yomahub/roguemap/index/Index.java @@ -1,5 +1,7 @@ package com.yomahub.roguemap.index; +import com.yomahub.roguemap.func.EntryConsumer; + /** * 索引接口,用于键值查找 * @@ -107,6 +109,13 @@ public interface Index { */ void clear(); + /** + * 从索引中移除所有条目,并对每个移除的条目执行操作 + * + * @param action 对每个被移除条目执行的操作 (address, size) + */ + void clear(EntryConsumer action); + /** * 关闭索引并释放资源 */ @@ -152,4 +161,11 @@ public interface Index { * @param baseAddress 基础地址,用于重新计算内存地址 */ void deserializeWithOffsets(long address, int size, long baseAddress); + + /** + * 遍历索引中的所有条目 + * + * @param action 对每个条目执行的操作 (address, size) + */ + void forEach(EntryConsumer action); } diff --git a/src/main/java/com/yomahub/roguemap/index/IntPrimitiveIndex.java b/src/main/java/com/yomahub/roguemap/index/IntPrimitiveIndex.java index 5c99180..071a78e 100644 --- a/src/main/java/com/yomahub/roguemap/index/IntPrimitiveIndex.java +++ b/src/main/java/com/yomahub/roguemap/index/IntPrimitiveIndex.java @@ -1,17 +1,18 @@ package com.yomahub.roguemap.index; +import com.yomahub.roguemap.func.EntryConsumer; import com.yomahub.roguemap.memory.UnsafeOps; import java.util.concurrent.locks.StampedLock; /** * 极致优化的Integer键索引 - 使用原始类型数组 - * + *

* 内存占用(100万条,负载因子0.75): * - keys: 4 bytes × 1,333,333 = 5.3 MB * - addresses: 8 bytes × 1,333,333 = 10.7 MB * - sizes: 4 bytes × 1,333,333 = 5.3 MB * - 总计: ~21.3 MB(实际存储100万条约16MB) - * + *

* 相比Long键索引,再节省25%内存 */ public class IntPrimitiveIndex implements Index { @@ -45,10 +46,10 @@ public IntPrimitiveIndex(int initialCapacity) { @Override public long put(Integer key, long address, int valueSize) { if (key == null || key == EMPTY_KEY || key == DELETED_KEY) { - throw new IllegalArgumentException("无效的键: " + key); + throw new IllegalArgumentException("Invalid key: " + key); } if (address == 0) { - throw new IllegalArgumentException("无效的地址: 0"); + throw new IllegalArgumentException("Invalid address: 0"); } long stamp = lock.writeLock(); @@ -245,8 +246,21 @@ public int size() { @Override public void clear() { + clear(null); + } + + @Override + public void clear(EntryConsumer action) { long stamp = lock.writeLock(); try { + if (action != null) { + for (int i = 0; i < keys.length; i++) { + int key = keys[i]; + if (key != EMPTY_KEY && key != DELETED_KEY) { + action.accept(addresses[i], sizes[i]); + } + } + } keys = new int[DEFAULT_CAPACITY]; addresses = new long[DEFAULT_CAPACITY]; sizes = new int[DEFAULT_CAPACITY]; @@ -277,13 +291,33 @@ public int serializedSize() { @Override public int serialize(long address) { // 原始类型索引暂不支持序列化 - throw new UnsupportedOperationException("IntPrimitiveIndex 暂不支持序列化"); + throw new UnsupportedOperationException("IntPrimitiveIndex does not support serialization temporarily"); } @Override public void deserialize(long address, int size) { // 原始类型索引暂不支持序列化 - throw new UnsupportedOperationException("IntPrimitiveIndex 暂不支持序列化"); + throw new UnsupportedOperationException("IntPrimitiveIndex does not support serialization temporarily"); + } + + @Override + public void forEach(EntryConsumer action) { + if (action == null) { + throw new IllegalArgumentException("Action cannot be null"); + } + long stamp = lock.readLock(); + try { + for (int i = 0; i < keys.length; i++) { + int key = keys[i]; + if (key != EMPTY_KEY && key != DELETED_KEY) { + long addr = addresses[i]; + int sz = sizes[i]; + action.accept(addr, sz); + } + } + } finally { + lock.unlockRead(stamp); + } } private int probe(int key) { diff --git a/src/main/java/com/yomahub/roguemap/index/LongPrimitiveIndex.java b/src/main/java/com/yomahub/roguemap/index/LongPrimitiveIndex.java index c9bfeb5..02c99f9 100644 --- a/src/main/java/com/yomahub/roguemap/index/LongPrimitiveIndex.java +++ b/src/main/java/com/yomahub/roguemap/index/LongPrimitiveIndex.java @@ -1,5 +1,6 @@ package com.yomahub.roguemap.index; +import com.yomahub.roguemap.func.EntryConsumer; import com.yomahub.roguemap.memory.UnsafeOps; import java.util.concurrent.locks.StampedLock; @@ -45,10 +46,10 @@ public LongPrimitiveIndex(int initialCapacity) { @Override public long put(Long key, long address, int valueSize) { if (key == null || key == EMPTY_KEY || key == DELETED_KEY) { - throw new IllegalArgumentException("无效的键: " + key); + throw new IllegalArgumentException("Invalid key: " + key); } if (address == 0) { - throw new IllegalArgumentException("无效的地址: 0"); + throw new IllegalArgumentException("Invalid address: 0"); } long stamp = lock.writeLock(); @@ -249,8 +250,21 @@ public int size() { @Override public void clear() { + clear(null); + } + + @Override + public void clear(EntryConsumer action) { long stamp = lock.writeLock(); try { + if (action != null) { + for (int i = 0; i < keys.length; i++) { + long key = keys[i]; + if (key != EMPTY_KEY && key != DELETED_KEY) { + action.accept(addresses[i], sizes[i]); + } + } + } keys = new long[DEFAULT_CAPACITY]; addresses = new long[DEFAULT_CAPACITY]; sizes = new int[DEFAULT_CAPACITY]; @@ -281,13 +295,33 @@ public int serializedSize() { @Override public int serialize(long address) { // 原始类型索引暂不支持序列化 - throw new UnsupportedOperationException("LongPrimitiveIndex 暂不支持序列化"); + throw new UnsupportedOperationException("LongPrimitiveIndex does not support serialization temporarily"); } @Override public void deserialize(long address, int size) { // 原始类型索引暂不支持序列化 - throw new UnsupportedOperationException("LongPrimitiveIndex 暂不支持序列化"); + throw new UnsupportedOperationException("LongPrimitiveIndex does not support serialization temporarily"); + } + + @Override + public void forEach(EntryConsumer action) { + if (action == null) { + throw new IllegalArgumentException("Action cannot be null"); + } + long stamp = lock.readLock(); + try { + for (int i = 0; i < keys.length; i++) { + long key = keys[i]; + if (key != EMPTY_KEY && key != DELETED_KEY) { + long addr = addresses[i]; + int sz = sizes[i]; + action.accept(addr, sz); + } + } + } finally { + lock.unlockRead(stamp); + } } /** diff --git a/src/main/java/com/yomahub/roguemap/index/SegmentedHashIndex.java b/src/main/java/com/yomahub/roguemap/index/SegmentedHashIndex.java index d3116fe..3e351b3 100644 --- a/src/main/java/com/yomahub/roguemap/index/SegmentedHashIndex.java +++ b/src/main/java/com/yomahub/roguemap/index/SegmentedHashIndex.java @@ -1,5 +1,6 @@ package com.yomahub.roguemap.index; +import com.yomahub.roguemap.func.EntryConsumer; import com.yomahub.roguemap.memory.UnsafeOps; import com.yomahub.roguemap.serialization.Codec; @@ -42,7 +43,7 @@ public SegmentedHashIndex(Codec keyCodec) { @SuppressWarnings("unchecked") public SegmentedHashIndex(Codec keyCodec, int segmentCount, int initialCapacityPerSegment) { if (segmentCount <= 0 || (segmentCount & (segmentCount - 1)) != 0) { - throw new IllegalArgumentException("段数必须是 2 的幂次方"); + throw new IllegalArgumentException("Segment count must be a power of 2"); } this.segments = new Segment[segmentCount]; @@ -58,10 +59,10 @@ public SegmentedHashIndex(Codec keyCodec, int segmentCount, int initialCapaci @Override public long put(K key, long address, int valueSize) { if (key == null) { - throw new IllegalArgumentException("键不能为 null"); + throw new IllegalArgumentException("Key cannot be null"); } if (address == 0) { - throw new IllegalArgumentException("无效的地址: 0"); + throw new IllegalArgumentException("Invalid address: 0"); } Segment segment = getSegment(key); @@ -173,10 +174,26 @@ public int size() { @Override public void clear() { + clear(null); + } + + @Override + public void clear(EntryConsumer action) { for (Segment segment : segments) { - segment.clear(); + long stamp = segment.lock.writeLock(); + try { + if (action != null) { + for (Entry entry : segment.map.values()) { + action.accept(entry.address, entry.size); + } + } + int count = segment.map.size(); + segment.map.clear(); + size.addAndGet(-count); + } finally { + segment.lock.unlockWrite(stamp); + } } - size.set(0); } @Override @@ -187,7 +204,7 @@ public void close() { @Override public int serializedSize() { if (keyCodec == null) { - throw new UnsupportedOperationException("无法序列化:keyCodec 为 null"); + throw new UnsupportedOperationException("Serialization not supported: keyCodec is null"); } int totalSize = 8; // segment count (4 bytes) + total entry count (4 bytes) @@ -202,7 +219,7 @@ public int serializedSize() { @Override public int serialize(long address) { if (keyCodec == null) { - throw new UnsupportedOperationException("无法序列化:keyCodec 为 null"); + throw new UnsupportedOperationException("Serialization not supported: keyCodec is null"); } long currentAddr = address; @@ -227,7 +244,7 @@ public int serialize(long address) { @Override public void deserialize(long address, int totalSize) { if (keyCodec == null) { - throw new UnsupportedOperationException("无法反序列化:keyCodec 为 null"); + throw new UnsupportedOperationException("Deserialization not supported: keyCodec is null"); } long currentAddr = address; @@ -243,7 +260,7 @@ public void deserialize(long address, int totalSize) { // 验证 segment count if (segmentCount != segments.length) { throw new IllegalStateException( - "段数不匹配:期望 " + segments.length + ",实际 " + segmentCount); + "Segment number mismatch: expected " + segments.length + ", actual " + segmentCount); } // 清空所有 segment @@ -287,7 +304,7 @@ int serializedSize(Codec keyCodec) { K key = entry.getKey(); int keySize = keyCodec.calculateSize(key); if (keySize < 0) { - throw new IllegalStateException("键的大小不能为负数"); + throw new IllegalStateException("Key size cannot be negative"); } size += 4 + keySize + 8 + 4; } @@ -313,7 +330,7 @@ int serialize(long address, Codec keyCodec) { int keySize = keyCodec.calculateSize(key); if (keySize < 0) { - throw new IllegalStateException("键的大小不能为负数"); + throw new IllegalStateException("Key size cannot be negative"); } // key size @@ -391,7 +408,7 @@ int serializeWithOffsets(long address, Codec keyCodec, long baseAddress) { int keySize = keyCodec.calculateSize(key); if (keySize < 0) { - throw new IllegalStateException("键的大小不能为负数"); + throw new IllegalStateException("Key size cannot be negative"); } // key size @@ -664,7 +681,7 @@ public void deserializeWithOffsets(long address, int totalSize, long baseAddress // 验证 segment count if (segmentCount != segments.length) { - throw new IllegalStateException("段数不匹配: 期望 " + segments.length + ", 实际 " + segmentCount); + throw new IllegalStateException("Segment number mismatch: expected " + segments.length + ", actual " + segmentCount); } // 清空所有 segment @@ -712,6 +729,23 @@ public void deserializeWithOffsets(long address, int totalSize, long baseAddress this.size.set(actualTotalSize); } + @Override + public void forEach(EntryConsumer action) { + if (action == null) { + throw new IllegalArgumentException("Action cannot be null"); + } + for (Segment segment : segments) { + long stamp = segment.lock.readLock(); + try { + for (Entry entry : segment.map.values()) { + action.accept(entry.address, entry.size); + } + } finally { + segment.lock.unlockRead(stamp); + } + } + } + /** * 根据键计算应该属于哪个段 */ diff --git a/src/main/java/com/yomahub/roguemap/memory/MmapAllocator.java b/src/main/java/com/yomahub/roguemap/memory/MmapAllocator.java index 597423a..90f808c 100644 --- a/src/main/java/com/yomahub/roguemap/memory/MmapAllocator.java +++ b/src/main/java/com/yomahub/roguemap/memory/MmapAllocator.java @@ -53,7 +53,7 @@ public MmapAllocator(String filePath, long fileSize) { */ public MmapAllocator(String filePath, long fileSize, boolean isTemporary) { if (fileSize <= 0) { - throw new IllegalArgumentException("文件大小必须为正数"); + throw new IllegalArgumentException("File size must be positive"); } this.isTemporary = isTemporary; @@ -63,7 +63,7 @@ public MmapAllocator(String filePath, long fileSize, boolean isTemporary) { this.file = TempFileManager.createTempFile(); } else { if (filePath == null || filePath.isEmpty()) { - throw new IllegalArgumentException("文件路径不能为空"); + throw new IllegalArgumentException("File path cannot be empty"); } this.file = new File(filePath); } @@ -131,7 +131,7 @@ public MmapAllocator(String filePath, long fileSize, boolean isTemporary) { } catch (Exception e) { close(); - throw new RuntimeException("创建内存映射文件失败: " + file.getAbsolutePath(), e); + throw new RuntimeException("Failed to create memory mapped file: " + file.getAbsolutePath(), e); } } @@ -194,7 +194,7 @@ public long getBaseAddress() { @Override public long allocate(int size) { if (size <= 0) { - throw new IllegalArgumentException("大小必须为正数: " + size); + throw new IllegalArgumentException("Size must be positive: " + size); } // 使用 CAS 操作分配偏移量 @@ -273,7 +273,7 @@ public void close() { } } } catch (Exception e) { - throw new RuntimeException("关闭内存映射文件失败", e); + throw new RuntimeException("Failed to close memory mapped file", e); } } @@ -307,15 +307,15 @@ public long getFileSize() { */ public String getStats() { StringBuilder sb = new StringBuilder(); - sb.append("MmapAllocator 统计信息:\n"); - sb.append(" 文件路径: ").append(getFilePath()).append("\n"); - sb.append(" 文件大小: ").append(fileSize).append(" 字节\n"); - sb.append(" 分段数: ").append(segmentCount).append("\n"); - sb.append(" 分段大小: ").append(segmentSize).append(" 字节\n"); - sb.append(" 已使用: ").append(usedMemory()).append(" 字节\n"); - sb.append(" 可用: ").append(availableMemory()).append(" 字节\n"); - sb.append(" 利用率: ").append(String.format("%.2f%%", 100.0 * usedMemory() / fileSize)); - sb.append("\n 临时文件: ").append(isTemporary ? "是" : "否"); + sb.append("MmapAllocator Stats:\n"); + sb.append(" File Path: ").append(getFilePath()).append("\n"); + sb.append(" File Size: ").append(fileSize).append(" bytes\n"); + sb.append(" Segment Count: ").append(segmentCount).append("\n"); + sb.append(" Segment Size: ").append(segmentSize).append(" bytes\n"); + sb.append(" Used: ").append(usedMemory()).append(" bytes\n"); + sb.append(" Available: ").append(availableMemory()).append(" bytes\n"); + sb.append(" Utilization: ").append(String.format("%.2f%%", 100.0 * usedMemory() / fileSize)); + sb.append("\n Temporary File: ").append(isTemporary ? "Yes" : "No"); return sb.toString(); } diff --git a/src/main/java/com/yomahub/roguemap/memory/SlabAllocator.java b/src/main/java/com/yomahub/roguemap/memory/SlabAllocator.java index 6249a73..6c81432 100644 --- a/src/main/java/com/yomahub/roguemap/memory/SlabAllocator.java +++ b/src/main/java/com/yomahub/roguemap/memory/SlabAllocator.java @@ -5,7 +5,7 @@ /** * Slab 内存分配器,用于高效的堆外内存管理 - * + *

* 该分配器通过将分配分组到大小类别来减少碎片。 * 每个大小类别维护一个空闲内存块池,用于快速分配/释放。 */ @@ -21,7 +21,7 @@ public class SlabAllocator implements Allocator { public SlabAllocator(long maxMemory) { if (maxMemory <= 0) { - throw new IllegalArgumentException("maxMemory 必须为正数"); + throw new IllegalArgumentException("maxMemory must be positive"); } this.maxMemory = maxMemory; this.totalAllocated = new AtomicLong(0); @@ -35,7 +35,7 @@ public SlabAllocator(long maxMemory) { @Override public long allocate(int size) { if (size <= 0) { - throw new IllegalArgumentException("大小必须为正数: " + size); + throw new IllegalArgumentException("Size must be positive: " + size); } // 检查内存限制 @@ -182,12 +182,12 @@ public static SlabAllocator createDefault() { */ public String getStats() { StringBuilder sb = new StringBuilder(); - sb.append("SlabAllocator 统计信息:\n"); - sb.append(" 总分配: ").append(totalAllocated()).append(" 字节\n"); - sb.append(" 已使用内存: ").append(usedMemory()).append(" 字节\n"); - sb.append(" 可用内存: ").append(availableMemory()).append(" 字节\n"); - sb.append(" 最大内存: ").append(maxMemory).append(" 字节\n"); - sb.append(" 利用率: ").append(String.format("%.2f%%", 100.0 * usedMemory() / maxMemory)); + sb.append("SlabAllocator Stats:\n"); + sb.append(" Total Allocated: ").append(totalAllocated()).append(" bytes\n"); + sb.append(" Used Memory: ").append(usedMemory()).append(" bytes\n"); + sb.append(" Available Memory: ").append(availableMemory()).append(" bytes\n"); + sb.append(" Max Memory: ").append(maxMemory).append(" bytes\n"); + sb.append(" Utilization: ").append(String.format("%.2f%%", 100.0 * usedMemory() / maxMemory)); return sb.toString(); } } diff --git a/src/main/java/com/yomahub/roguemap/memory/UnsafeOps.java b/src/main/java/com/yomahub/roguemap/memory/UnsafeOps.java index ee6a27e..1e2210f 100644 --- a/src/main/java/com/yomahub/roguemap/memory/UnsafeOps.java +++ b/src/main/java/com/yomahub/roguemap/memory/UnsafeOps.java @@ -21,7 +21,7 @@ public class UnsafeOps { field.setAccessible(true); UNSAFE = (Unsafe) field.get(null); } catch (Exception e) { - throw new RuntimeException("获取 Unsafe 实例失败", e); + throw new RuntimeException("Failed to get Unsafe instance", e); } } @@ -33,11 +33,11 @@ public class UnsafeOps { */ public static long allocate(long size) { if (size <= 0) { - throw new IllegalArgumentException("大小必须为正数: " + size); + throw new IllegalArgumentException("Size must be positive: " + size); } long address = UNSAFE.allocateMemory(size); if (address == 0) { - throw new OutOfMemoryError("分配 " + size + " 字节失败"); + throw new OutOfMemoryError("Failed to allocate " + size + " bytes"); } return address; } @@ -51,11 +51,11 @@ public static long allocate(long size) { */ public static long reallocate(long address, long newSize) { if (newSize <= 0) { - throw new IllegalArgumentException("大小必须为正数: " + newSize); + throw new IllegalArgumentException("Size must be positive: " + newSize); } long newAddress = UNSAFE.reallocateMemory(address, newSize); if (newAddress == 0) { - throw new OutOfMemoryError("重新分配到 " + newSize + " 字节失败"); + throw new OutOfMemoryError("Failed to reallocate to " + newSize + " bytes"); } return newAddress; } @@ -205,7 +205,7 @@ public static boolean compareAndSwapLong(long address, long expected, long updat */ public static long getDirectBufferAddress(ByteBuffer buffer) { if (!buffer.isDirect()) { - throw new IllegalArgumentException("Buffer 必须是 direct 类型"); + throw new IllegalArgumentException("Buffer must be direct"); } return ((sun.nio.ch.DirectBuffer) buffer).address(); } diff --git a/src/main/java/com/yomahub/roguemap/serialization/Codec.java b/src/main/java/com/yomahub/roguemap/serialization/Codec.java index 730247c..3601cc2 100644 --- a/src/main/java/com/yomahub/roguemap/serialization/Codec.java +++ b/src/main/java/com/yomahub/roguemap/serialization/Codec.java @@ -48,6 +48,6 @@ default boolean isFixedSize() { * @return 固定的字节大小 */ default int getFixedSize() { - throw new UnsupportedOperationException("不是固定大小的编解码器"); + throw new UnsupportedOperationException("Codec is not fixed size"); } } diff --git a/src/main/java/com/yomahub/roguemap/storage/MmapStorage.java b/src/main/java/com/yomahub/roguemap/storage/MmapStorage.java index bf7c08f..a70e343 100644 --- a/src/main/java/com/yomahub/roguemap/storage/MmapStorage.java +++ b/src/main/java/com/yomahub/roguemap/storage/MmapStorage.java @@ -5,7 +5,7 @@ /** * 内存映射文件存储引擎 - * + *

* 使用 MappedByteBuffer 将文件映射到内存,利用操作系统页缓存 * 适合大数据量持久化场景 */ @@ -15,7 +15,7 @@ public class MmapStorage implements StorageEngine { public MmapStorage(MmapAllocator allocator) { if (allocator == null) { - throw new IllegalArgumentException("Allocator 不能为 null"); + throw new IllegalArgumentException("Allocator cannot be null"); } this.allocator = allocator; } @@ -23,13 +23,13 @@ public MmapStorage(MmapAllocator allocator) { @Override public void put(long address, byte[] data, int offset, int length) { if (address == 0) { - throw new IllegalArgumentException("无效的地址: 0"); + throw new IllegalArgumentException("Invalid address: 0"); } if (data == null) { - throw new IllegalArgumentException("数据不能为 null"); + throw new IllegalArgumentException("Data cannot be null"); } if (offset < 0 || length < 0 || offset + length > data.length) { - throw new IllegalArgumentException("无效的偏移量或长度"); + throw new IllegalArgumentException("Invalid offset or length"); } UnsafeOps.copyFromArray(data, offset, address, length); @@ -38,10 +38,10 @@ public void put(long address, byte[] data, int offset, int length) { @Override public byte[] get(long address, int length) { if (address == 0) { - throw new IllegalArgumentException("无效的地址: 0"); + throw new IllegalArgumentException("Invalid address: 0"); } if (length < 0) { - throw new IllegalArgumentException("无效的长度: " + length); + throw new IllegalArgumentException("Invalid length: " + length); } byte[] data = new byte[length]; diff --git a/src/main/java/com/yomahub/roguemap/storage/OffHeapStorage.java b/src/main/java/com/yomahub/roguemap/storage/OffHeapStorage.java index f582dfc..446c69d 100644 --- a/src/main/java/com/yomahub/roguemap/storage/OffHeapStorage.java +++ b/src/main/java/com/yomahub/roguemap/storage/OffHeapStorage.java @@ -5,7 +5,7 @@ /** * 堆外内存存储引擎 - * + *

* 使用 DirectByteBuffer 在本地内存中存储数据 */ public class OffHeapStorage implements StorageEngine { @@ -14,7 +14,7 @@ public class OffHeapStorage implements StorageEngine { public OffHeapStorage(Allocator allocator) { if (allocator == null) { - throw new IllegalArgumentException("Allocator 不能为 null"); + throw new IllegalArgumentException("Allocator cannot be null"); } this.allocator = allocator; } @@ -22,13 +22,13 @@ public OffHeapStorage(Allocator allocator) { @Override public void put(long address, byte[] data, int offset, int length) { if (address == 0) { - throw new IllegalArgumentException("无效的地址: 0"); + throw new IllegalArgumentException("Invalid address: 0"); } if (data == null) { - throw new IllegalArgumentException("数据不能为 null"); + throw new IllegalArgumentException("Data cannot be null"); } if (offset < 0 || length < 0 || offset + length > data.length) { - throw new IllegalArgumentException("无效的偏移量或长度"); + throw new IllegalArgumentException("Invalid offset or length"); } UnsafeOps.copyFromArray(data, offset, address, length); @@ -37,10 +37,10 @@ public void put(long address, byte[] data, int offset, int length) { @Override public byte[] get(long address, int length) { if (address == 0) { - throw new IllegalArgumentException("无效的地址: 0"); + throw new IllegalArgumentException("Invalid address: 0"); } if (length < 0) { - throw new IllegalArgumentException("无效的长度: " + length); + throw new IllegalArgumentException("Invalid length: " + length); } byte[] data = new byte[length]; diff --git a/src/main/java/com/yomahub/roguemap/util/TempFileManager.java b/src/main/java/com/yomahub/roguemap/util/TempFileManager.java index f6846d1..2260995 100644 --- a/src/main/java/com/yomahub/roguemap/util/TempFileManager.java +++ b/src/main/java/com/yomahub/roguemap/util/TempFileManager.java @@ -47,7 +47,7 @@ public static File createTempFile() { return tempFile; } catch (Exception e) { - throw new RuntimeException("创建临时文件失败", e); + throw new RuntimeException("Failed to create temp file", e); } } @@ -82,7 +82,7 @@ public static void registerCleanupHook(File file, MappedByteBuffer... buffers) { } } catch (Exception e) { // Shutdown 过程中不抛出异常 - System.err.println("清理临时文件失败: " + file.getAbsolutePath() + ", " + e.getMessage()); + System.err.println("Failed to clean up temp file: " + file.getAbsolutePath() + ", " + e.getMessage()); } }, "RogueMap-TempFile-Cleanup"); @@ -124,10 +124,10 @@ public static void forceUnmap(MappedByteBuffer buffer) { invokeCleaner.invoke(unsafe, buffer); } catch (Exception ex) { // 如果都失败了,记录警告 - System.err.println("警告: 无法强制 unmap MappedByteBuffer: " + ex.getMessage()); + System.err.println("Warning: Failed to force unmap MappedByteBuffer: " + ex.getMessage()); } } catch (Exception e) { - System.err.println("警告: unmap MappedByteBuffer 时发生异常: " + e.getMessage()); + System.err.println("Warning: Exception occurred while unmapping MappedByteBuffer: " + e.getMessage()); } } @@ -164,7 +164,7 @@ public static void cleanupOldTempFiles() { .forEach(path -> { try { Files.delete(path); - System.out.println("清理过期临时文件: " + path.getFileName()); + System.out.println("Cleaning up old temp file: " + path.getFileName()); } catch (IOException e) { // 忽略删除失败的情况 } @@ -172,7 +172,7 @@ public static void cleanupOldTempFiles() { } } catch (Exception e) { // 清理失败不影响程序运行 - System.err.println("清理过期临时文件时发生错误: " + e.getMessage()); + System.err.println("Error occurred while cleaning up old temp files: " + e.getMessage()); } }