or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-operations.mdindex.mdindexing.mdquerying-views.mdserialization.mdstorage-implementations.mdtype-information.md

storage-implementations.mddocs/

0

# Storage Implementations

1

2

In-memory and persistent storage backends with different performance and durability characteristics. Choose the appropriate implementation based on your application's performance, persistence, and memory requirements.

3

4

## Capabilities

5

6

### InMemoryStore

7

8

Fast in-memory storage implementation that keeps all data deserialized in memory for maximum performance.

9

10

```java { .api }

11

/**

12

* Implementation of KVStore that keeps data deserialized in memory. This store does not index

13

* data; instead, whenever iterating over an indexed field, the stored data is copied and sorted

14

* according to the index. This saves memory but makes iteration more expensive.

15

*/

16

public class InMemoryStore implements KVStore {

17

/**

18

* Creates a new in-memory store.

19

*/

20

public InMemoryStore();

21

}

22

```

23

24

**Characteristics:**

25

- **Performance**: Fastest for read/write operations

26

- **Memory Usage**: Keeps all data in memory

27

- **Persistence**: Data lost when application stops

28

- **Indexing**: Sorts data on-demand during iteration

29

- **Thread Safety**: Thread-safe for concurrent access

30

31

**Usage Examples:**

32

33

```java

34

// Create an in-memory store

35

KVStore store = new InMemoryStore();

36

37

// Fast writes - data kept in memory

38

Person person = new Person("p1", "Alice", 30);

39

store.write(person); // Very fast

40

41

// Fast reads - no disk I/O

42

Person retrieved = store.read(Person.class, "p1"); // Very fast

43

44

// Iteration sorts data on-demand

45

for (Person p : store.view(Person.class).index("age")) {

46

System.out.println(p.name + " is " + p.age); // Sorts during iteration

47

}

48

49

// Data is lost when store is closed or application exits

50

store.close(); // All data lost

51

```

52

53

**Best Use Cases:**

54

- Caching and temporary data storage

55

- High-performance scenarios where persistence isn't required

56

- Development and testing environments

57

- Applications with limited data sets that fit in memory

58

59

### LevelDB

60

61

Persistent storage implementation using LevelDB for durability and efficient indexed access.

62

63

```java { .api }

64

/**

65

* Implementation of KVStore that uses LevelDB as the underlying data store.

66

*/

67

public class LevelDB implements KVStore {

68

/**

69

* Creates a LevelDB store at the specified path with default serializer.

70

* @param path - Directory path where LevelDB files will be stored

71

* @throws Exception If store creation or initialization fails

72

*/

73

public LevelDB(File path) throws Exception;

74

75

/**

76

* Creates a LevelDB store at the specified path with custom serializer.

77

* @param path - Directory path where LevelDB files will be stored

78

* @param serializer - Custom serializer for object persistence

79

* @throws Exception If store creation or initialization fails

80

*/

81

public LevelDB(File path, KVStoreSerializer serializer) throws Exception;

82

}

83

```

84

85

**Characteristics:**

86

- **Performance**: Slower than in-memory but optimized for disk operations

87

- **Memory Usage**: Uses disk storage with configurable caching

88

- **Persistence**: Data survives application restarts

89

- **Indexing**: Maintains persistent indices on disk for efficient queries

90

- **Thread Safety**: Thread-safe for concurrent access

91

- **Compression**: Automatic data compression to save disk space

92

93

**Usage Examples:**

94

95

```java

96

// Create a persistent LevelDB store

97

KVStore store = new LevelDB(new File("./my-data-store"));

98

99

// Or with custom serializer

100

KVStoreSerializer customSerializer = new MyCustomSerializer();

101

KVStore storeWithCustomSerializer = new LevelDB(new File("./custom-store"), customSerializer);

102

103

// Writes are persisted to disk

104

Person person = new Person("p1", "Alice", 30);

105

store.write(person); // Data written to disk

106

107

// Data survives application restart

108

store.close();

109

110

// Reopen the same store later

111

KVStore reopenedStore = new LevelDB(new File("./my-data-store"));

112

Person retrieved = reopenedStore.read(Person.class, "p1"); // Data still there!

113

114

// Efficient indexed queries using disk-based indices

115

for (Person p : reopenedStore.view(Person.class).index("age").first(25).last(35)) {

116

System.out.println(p.name + " is " + p.age); // Uses persistent index

117

}

118

119

reopenedStore.close();

120

```

121

122

**Best Use Cases:**

123

- Production applications requiring data persistence

124

- Large datasets that don't fit in memory

125

- Applications that need to preserve data across restarts

126

- Scenarios where query performance is important

127

128

### Version Compatibility and Internal Management

129

130

LevelDB stores include version checking and use internal keys for metadata and type alias management.

131

132

```java { .api }

133

/**

134

* Exception thrown when the store implementation is not compatible with the underlying data.

135

*/

136

public class UnsupportedStoreVersionException extends IOException {

137

}

138

139

/**

140

* Internal constants used by LevelDB implementation for store management

141

*/

142

static final long STORE_VERSION = 1L;

143

static final byte[] STORE_VERSION_KEY = "__version__".getBytes(UTF_8);

144

static final byte[] METADATA_KEY = "__meta__".getBytes(UTF_8);

145

static final byte[] TYPE_ALIASES_KEY = "__types__".getBytes(UTF_8);

146

```

147

148

**Usage Examples:**

149

150

```java

151

try {

152

// Attempt to open an existing LevelDB store

153

KVStore store = new LevelDB(new File("./legacy-store"));

154

// Store opened successfully

155

} catch (UnsupportedStoreVersionException e) {

156

// The store was created with an incompatible version

157

System.err.println("Store version incompatible - data migration required");

158

// Handle version incompatibility (backup, migrate, etc.)

159

}

160

```

161

162

### Performance Comparison

163

164

**Write Performance:**

165

```java

166

// Benchmark: Writing 10,000 objects

167

168

// InMemoryStore - Fastest

169

KVStore memStore = new InMemoryStore();

170

long startTime = System.currentTimeMillis();

171

for (int i = 0; i < 10000; i++) {

172

memStore.write(new Person("p" + i, "Name" + i, 20 + (i % 50)));

173

}

174

long memTime = System.currentTimeMillis() - startTime;

175

System.out.println("InMemoryStore: " + memTime + "ms");

176

177

// LevelDB - Slower but persistent

178

KVStore levelStore = new LevelDB(new File("./benchmark-store"));

179

startTime = System.currentTimeMillis();

180

for (int i = 0; i < 10000; i++) {

181

levelStore.write(new Person("p" + i, "Name" + i, 20 + (i % 50)));

182

}

183

long levelTime = System.currentTimeMillis() - startTime;

184

System.out.println("LevelDB: " + levelTime + "ms");

185

```

186

187

**Query Performance:**

188

```java

189

// Indexed queries

190

191

// InMemoryStore - Sorts on each iteration

192

for (Person p : memStore.view(Person.class).index("age").first(30).last(40)) {

193

// Data sorted during iteration

194

}

195

196

// LevelDB - Uses pre-built disk indices

197

for (Person p : levelStore.view(Person.class).index("age").first(30).last(40)) {

198

// Uses persistent index for efficient access

199

}

200

```

201

202

### Memory Management

203

204

**InMemoryStore Memory Usage:**

205

```java

206

KVStore memStore = new InMemoryStore();

207

208

// All objects kept in memory

209

for (int i = 0; i < 100000; i++) {

210

memStore.write(new LargeObject("obj" + i, generateLargeData()));

211

// Memory usage grows with each write

212

}

213

214

// Memory usage = number of objects × average object size

215

// Monitor with: Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()

216

```

217

218

**LevelDB Memory Usage:**

219

```java

220

KVStore levelStore = new LevelDB(new File("./large-store"));

221

222

// Objects stored on disk, minimal memory usage

223

for (int i = 0; i < 100000; i++) {

224

levelStore.write(new LargeObject("obj" + i, generateLargeData()));

225

// Memory usage remains relatively constant

226

}

227

228

// Memory usage = cache size + working set (much smaller than data size)

229

```

230

231

### Store Selection Guidelines

232

233

**Choose InMemoryStore when:**

234

- Maximum performance is required

235

- Data size fits comfortably in available memory

236

- Data doesn't need to persist across application restarts

237

- Caching temporary or computed data

238

- Development and testing scenarios

239

240

**Choose LevelDB when:**

241

- Data must persist across application restarts

242

- Working with large datasets that may not fit in memory

243

- Query performance on indexed fields is important

244

- Production environments requiring reliability

245

- Need efficient range queries and sorting

246

247

**Hybrid Approach:**

248

```java

249

// Use both stores for different purposes

250

KVStore cache = new InMemoryStore(); // For frequently accessed data

251

KVStore persistent = new LevelDB(new File("./data")); // For permanent storage

252

253

// Cache frequently accessed users in memory

254

User frequentUser = persistent.read(User.class, "frequent_user_123");

255

cache.write(frequentUser); // Cache for fast access

256

257

// Read from cache first, fall back to persistent store

258

User user;

259

try {

260

user = cache.read(User.class, userId); // Try cache first

261

} catch (NoSuchElementException e) {

262

user = persistent.read(User.class, userId); // Fall back to persistent

263

cache.write(user); // Cache for next time

264

}

265

```