or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-channels.mdbyte-order.mdcharacter-encoding.mdindex.mdmemory-management.mdobject-pooling.mdpacket-io.md

object-pooling.mddocs/

0

# Object Pooling

1

2

Resource management system providing efficient object reuse patterns with configurable capacity and lifecycle management.

3

4

## Capabilities

5

6

### ObjectPool Interface

7

8

Generic object pooling interface extending Closeable for automatic resource management and efficient object reuse.

9

10

```kotlin { .api }

11

/**

12

* Generic object pool interface for efficient resource management.

13

* Provides object reuse to reduce allocation overhead and garbage collection pressure.

14

*/

15

interface ObjectPool<T> : Closeable {

16

/** Maximum number of objects the pool can hold */

17

val capacity: Int

18

19

/**

20

* Borrow an object from the pool.

21

* Creates a new instance if pool is empty and capacity allows.

22

* @return object instance ready for use

23

*/

24

fun borrow(): T

25

26

/**

27

* Return an object to the pool for future reuse.

28

* Object should be reset to clean state before recycling.

29

* @param instance object to return to pool

30

*/

31

fun recycle(instance: T)

32

33

/**

34

* Dispose all objects in the pool and release resources.

35

* Pool becomes unusable after disposal.

36

*/

37

fun dispose()

38

39

/**

40

* Close the pool (same as dispose).

41

* Implements Closeable interface for use-with-resources patterns.

42

*/

43

override fun close() = dispose()

44

}

45

```

46

47

**Usage Examples:**

48

49

```kotlin

50

import io.ktor.utils.io.pool.*

51

52

// Create a custom pool for StringBuilder objects

53

val stringBuilderPool = object : DefaultPool<StringBuilder>(capacity = 10) {

54

override fun produce(): StringBuilder = StringBuilder()

55

override fun reset(instance: StringBuilder): StringBuilder {

56

instance.clear()

57

return instance

58

}

59

}

60

61

// Use the pool

62

val sb = stringBuilderPool.borrow()

63

try {

64

sb.append("Hello ")

65

sb.append("World")

66

val result = sb.toString()

67

println(result)

68

} finally {

69

stringBuilderPool.recycle(sb)

70

}

71

72

// Pool cleanup

73

stringBuilderPool.close()

74

```

75

76

### Pool Implementation Classes

77

78

Abstract base classes and concrete implementations for different pooling strategies.

79

80

```kotlin { .api }

81

/**

82

* Abstract base class for pools with zero capacity.

83

* Always creates new instances instead of pooling.

84

*/

85

abstract class NoPoolImpl<T> : ObjectPool<T> {

86

override val capacity: Int = 0

87

88

/**

89

* Create a new instance (not pooled).

90

* @return new object instance

91

*/

92

protected abstract fun produce(): T

93

94

override fun borrow(): T = produce()

95

override fun recycle(instance: T) {} // No-op for zero capacity

96

override fun dispose() {} // No-op for zero capacity

97

}

98

99

/**

100

* Abstract pool that produces at most one instance.

101

* Suitable for expensive-to-create singleton-like objects.

102

*/

103

abstract class SingleInstancePool<T> : ObjectPool<T> {

104

override val capacity: Int = 1

105

106

/**

107

* Create the single instance.

108

* @return new object instance

109

*/

110

protected abstract fun produce(): T

111

112

/**

113

* Reset instance to clean state before reuse.

114

* @param instance object to reset

115

* @return reset object (same instance or replacement)

116

*/

117

protected abstract fun reset(instance: T): T

118

119

override fun borrow(): T

120

override fun recycle(instance: T)

121

override fun dispose()

122

}

123

124

/**

125

* Default pool implementation with configurable capacity.

126

* Thread-safe implementation optimized for concurrent access.

127

*/

128

abstract class DefaultPool<T>(override val capacity: Int) : ObjectPool<T> {

129

/**

130

* Create a new instance when pool is empty.

131

* @return new object instance

132

*/

133

protected abstract fun produce(): T

134

135

/**

136

* Reset instance to clean state before recycling.

137

* @param instance object to reset

138

* @return reset object (same instance or replacement)

139

*/

140

protected open fun reset(instance: T): T = instance

141

142

/**

143

* Validate instance before recycling.

144

* @param instance object to validate

145

* @return true if instance can be recycled

146

*/

147

protected open fun validateInstance(instance: T): Boolean = true

148

149

/**

150

* Dispose an instance when it cannot be recycled.

151

* @param instance object to dispose

152

*/

153

protected open fun disposeInstance(instance: T) {}

154

155

override fun borrow(): T

156

override fun recycle(instance: T)

157

override fun dispose()

158

}

159

```

160

161

**Usage Examples:**

162

163

```kotlin

164

import io.ktor.utils.io.pool.*

165

166

// Custom pool with validation

167

class ByteArrayPool(capacity: Int, private val arraySize: Int) : DefaultPool<ByteArray>(capacity) {

168

override fun produce(): ByteArray = ByteArray(arraySize)

169

170

override fun reset(instance: ByteArray): ByteArray {

171

instance.fill(0) // Clear array

172

return instance

173

}

174

175

override fun validateInstance(instance: ByteArray): Boolean {

176

return instance.size == arraySize // Ensure correct size

177

}

178

}

179

180

val pool = ByteArrayPool(capacity = 5, arraySize = 1024)

181

182

// Use pool with validation

183

val array = pool.borrow()

184

// ... use array ...

185

pool.recycle(array) // Will be validated and reset

186

187

// Single instance pool example

188

class ExpensiveResourcePool : SingleInstancePool<ExpensiveResource>() {

189

override fun produce(): ExpensiveResource = ExpensiveResource()

190

191

override fun reset(instance: ExpensiveResource): ExpensiveResource {

192

instance.reset()

193

return instance

194

}

195

}

196

```

197

198

### ByteArrayPool Object

199

200

Pre-configured global pool for byte arrays with optimized settings for I/O operations.

201

202

```kotlin { .api }

203

/**

204

* Global byte array pool optimized for I/O operations.

205

* Provides efficient reuse of byte arrays to reduce allocation overhead.

206

*/

207

object ByteArrayPool : ObjectPool<ByteArray> {

208

override val capacity: Int

209

210

/**

211

* Borrow a byte array from the global pool.

212

* Array size is implementation-specific and optimized for common I/O operations.

213

* @return byte array ready for use

214

*/

215

override fun borrow(): ByteArray

216

217

/**

218

* Return byte array to the global pool.

219

* Array will be reused for future borrow() calls.

220

* @param instance byte array to recycle

221

*/

222

override fun recycle(instance: ByteArray)

223

224

override fun dispose()

225

override fun close() = dispose()

226

}

227

```

228

229

**Usage Examples:**

230

231

```kotlin

232

import io.ktor.utils.io.pool.*

233

import io.ktor.utils.io.*

234

235

// Use global byte array pool

236

val buffer = ByteArrayPool.borrow()

237

try {

238

// Perform I/O operations with the buffer

239

val channel: ByteReadChannel = TODO()

240

val bytesRead = channel.readAvailable(buffer, 0, buffer.size)

241

242

// Process data in buffer

243

processData(buffer, bytesRead)

244

} finally {

245

// Always return to pool

246

ByteArrayPool.recycle(buffer)

247

}

248

249

// Integration with channels

250

suspend fun efficientCopy(source: ByteReadChannel, dest: ByteWriteChannel) {

251

val buffer = ByteArrayPool.borrow()

252

try {

253

while (!source.isClosedForRead) {

254

val bytesRead = source.readAvailable(buffer, 0, buffer.size)

255

if (bytesRead > 0) {

256

dest.writeFully(buffer, 0, bytesRead)

257

}

258

}

259

} finally {

260

ByteArrayPool.recycle(buffer)

261

}

262

}

263

```

264

265

### Pool Utility Functions

266

267

Utility functions for convenient pool usage with automatic resource management.

268

269

```kotlin { .api }

270

/**

271

* Use an object from the pool with automatic return.

272

* Ensures object is returned to pool even if block throws exception.

273

* @param block operation to perform with borrowed object

274

* @return result of the block operation

275

*/

276

inline fun <T : Any, R> ObjectPool<T>.useInstance(block: (T) -> R): R

277

```

278

279

**Usage Examples:**

280

281

```kotlin

282

import io.ktor.utils.io.pool.*

283

284

// Safe pool usage with automatic cleanup

285

val result = ByteArrayPool.useInstance { buffer ->

286

// Use buffer safely - it will be automatically returned

287

performIOOperation(buffer)

288

"Operation completed"

289

}

290

291

// Custom pool with useInstance

292

class StringBuilderPool : DefaultPool<StringBuilder>(capacity = 10) {

293

override fun produce(): StringBuilder = StringBuilder()

294

override fun reset(instance: StringBuilder): StringBuilder {

295

instance.clear()

296

return instance

297

}

298

}

299

300

val pool = StringBuilderPool()

301

302

val formattedString = pool.useInstance { sb ->

303

sb.append("User: ")

304

sb.append("Alice")

305

sb.append(", Age: ")

306

sb.append(25)

307

sb.toString()

308

}

309

310

// Multiple nested pool usage

311

val complexResult = pool.useInstance { outerSb ->

312

outerSb.append("Outer: ")

313

314

val innerResult = pool.useInstance { innerSb ->

315

innerSb.append("Inner content")

316

innerSb.toString()

317

}

318

319

outerSb.append(innerResult)

320

outerSb.toString()

321

}

322

```

323

324

### Pool Configuration and Best Practices

325

326

Configuration options and usage patterns for optimal pool performance.

327

328

```kotlin { .api }

329

/**

330

* No-pool implementation that always creates new instances.

331

* Use when pooling overhead exceeds benefits.

332

*/

333

fun <T> ObjectPool.Companion.NoPool(): ObjectPool<T> where T : Any

334

335

/**

336

* Create a simple pool with basic configuration.

337

* @param capacity maximum objects to pool

338

* @param produce factory function for creating instances

339

* @param reset optional reset function for cleaning instances

340

* @return configured pool instance

341

*/

342

fun <T> ObjectPool.Companion.create(

343

capacity: Int,

344

produce: () -> T,

345

reset: (T) -> T = { it }

346

): ObjectPool<T>

347

```

348

349

**Best Practices Examples:**

350

351

```kotlin

352

import io.ktor.utils.io.pool.*

353

354

// Choose appropriate pool size based on usage patterns

355

class OptimizedBufferPool {

356

// Small pool for frequent, short-lived operations

357

private val smallBuffers = object : DefaultPool<ByteArray>(capacity = 16) {

358

override fun produce() = ByteArray(1024)

359

}

360

361

// Larger pool for less frequent, longer-lived operations

362

private val largeBuffers = object : DefaultPool<ByteArray>(capacity = 4) {

363

override fun produce() = ByteArray(64 * 1024)

364

}

365

366

fun borrowSmall(): ByteArray = smallBuffers.borrow()

367

fun recycleSmall(buffer: ByteArray) = smallBuffers.recycle(buffer)

368

369

fun borrowLarge(): ByteArray = largeBuffers.borrow()

370

fun recycleLarge(buffer: ByteArray) = largeBuffers.recycle(buffer)

371

}

372

373

// Pool with validation and cleanup

374

class ValidatingPool<T>(

375

capacity: Int,

376

private val factory: () -> T,

377

private val validator: (T) -> Boolean,

378

private val cleaner: (T) -> T

379

) : DefaultPool<T>(capacity) {

380

381

override fun produce(): T = factory()

382

383

override fun validateInstance(instance: T): Boolean = validator(instance)

384

385

override fun reset(instance: T): T = cleaner(instance)

386

}

387

388

// Thread-safe usage pattern

389

class ThreadSafePoolUser {

390

private val pool = object : DefaultPool<StringBuilder>(10) {

391

override fun produce() = StringBuilder()

392

override fun reset(instance: StringBuilder) = instance.apply { clear() }

393

}

394

395

fun formatMessage(user: String, message: String): String {

396

return pool.useInstance { sb ->

397

sb.append("[")

398

sb.append(System.currentTimeMillis())

399

sb.append("] ")

400

sb.append(user)

401

sb.append(": ")

402

sb.append(message)

403

sb.toString()

404

}

405

}

406

}

407

408

// Resource lifecycle management

409

class ManagedPoolExample : AutoCloseable {

410

private val pools = mutableListOf<ObjectPool<*>>()

411

412

fun <T> createPool(

413

capacity: Int,

414

factory: () -> T,

415

cleaner: (T) -> T = { it }

416

): ObjectPool<T> {

417

val pool = object : DefaultPool<T>(capacity) {

418

override fun produce() = factory()

419

override fun reset(instance: T) = cleaner(instance)

420

}

421

pools.add(pool)

422

return pool

423

}

424

425

override fun close() {

426

pools.forEach { it.dispose() }

427

pools.clear()

428

}

429

}

430

```