or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

concurrent-histograms.mdcore-operations.mddouble-histograms.mdindex.mditerators.mdrecorders.mdserialization.mdspecialized-variants.mdutilities.md

serialization.mddocs/

0

# Serialization and Persistence

1

2

Comprehensive encoding, decoding, and log processing capabilities for histogram data persistence and exchange. HdrHistogram provides multiple formats and tools for storing, transmitting, and processing histogram data.

3

4

## EncodableHistogram

5

6

Abstract base class for histograms that support encoding and decoding operations.

7

8

```java { .api }

9

public abstract class EncodableHistogram implements Serializable {

10

11

// Encoding methods

12

abstract int getNeededByteBufferCapacity();

13

abstract int encodeIntoByteBuffer(ByteBuffer targetBuffer);

14

abstract int encodeIntoCompressedByteBuffer(ByteBuffer targetBuffer, int compressionLevel);

15

16

// Metadata methods

17

abstract long getStartTimeStamp();

18

abstract void setStartTimeStamp(long startTimeStamp);

19

abstract long getEndTimeStamp();

20

abstract void setEndTimeStamp(long endTimeStamp);

21

abstract String getTag();

22

abstract void setTag(String tag);

23

abstract double getMaxValueAsDouble();

24

25

// Static decoding methods

26

static EncodableHistogram decodeFromByteBuffer(ByteBuffer buffer,

27

long minBarForHighestTrackableValue);

28

static EncodableHistogram decodeFromCompressedByteBuffer(ByteBuffer buffer,

29

long minBarForHighestTrackableValue);

30

}

31

```

32

33

## Binary Encoding and Decoding

34

35

### Encoding Histograms to ByteBuffer

36

37

```java

38

// Encode histogram to binary format

39

Histogram histogram = createSampleHistogram();

40

41

// Calculate required buffer size

42

int bufferSize = histogram.getNeededByteBufferCapacity();

43

ByteBuffer buffer = ByteBuffer.allocate(bufferSize);

44

45

// Encode histogram

46

int bytesWritten = histogram.encodeIntoByteBuffer(buffer);

47

System.out.printf("Encoded histogram in %d bytes%n", bytesWritten);

48

49

// Prepare buffer for reading

50

buffer.flip();

51

52

// The buffer now contains the encoded histogram

53

byte[] histogramData = new byte[bytesWritten];

54

buffer.get(histogramData);

55

```

56

57

### Compressed Encoding

58

59

```java

60

// Encode with compression for smaller size

61

Histogram histogram = createSampleHistogram();

62

63

int bufferSize = histogram.getNeededByteBufferCapacity();

64

ByteBuffer compressedBuffer = ByteBuffer.allocate(bufferSize);

65

66

// Compress with deflate compression (0-9 compression levels)

67

int compressedSize = histogram.encodeIntoCompressedByteBuffer(compressedBuffer, 6);

68

System.out.printf("Compressed histogram to %d bytes (level 6)%n", compressedSize);

69

70

// Compare compression ratios

71

int uncompressedSize = histogram.getNeededByteBufferCapacity();

72

double compressionRatio = (double) compressedSize / uncompressedSize;

73

System.out.printf("Compression ratio: %.2f (%.1f%% reduction)%n",

74

compressionRatio, (1.0 - compressionRatio) * 100);

75

```

76

77

### Decoding Histograms from ByteBuffer

78

79

```java

80

// Decode standard encoded histogram

81

ByteBuffer encodedBuffer = getEncodedHistogramBuffer();

82

Histogram decoded = Histogram.decodeFromByteBuffer(encodedBuffer, 1000);

83

84

System.out.printf("Decoded histogram: %d samples, max=%d%n",

85

decoded.getTotalCount(), decoded.getMaxValue());

86

87

// Decode compressed histogram

88

ByteBuffer compressedBuffer = getCompressedHistogramBuffer();

89

Histogram decompressed = Histogram.decodeFromCompressedByteBuffer(compressedBuffer, 1000);

90

91

// Verify integrity

92

if (decoded.equals(decompressed)) {

93

System.out.println("Compression/decompression preserves data integrity");

94

}

95

```

96

97

### Polymorphic Decoding

98

99

```java

100

// Decode without knowing specific histogram type

101

ByteBuffer unknownHistogramBuffer = getHistogramBuffer();

102

103

// Returns appropriate type (Histogram or DoubleHistogram)

104

EncodableHistogram histogram = EncodableHistogram.decodeFromByteBuffer(unknownHistogramBuffer, 1000);

105

106

if (histogram instanceof Histogram) {

107

Histogram intHistogram = (Histogram) histogram;

108

System.out.printf("Integer histogram: P95=%d%n",

109

intHistogram.getValueAtPercentile(95.0));

110

} else if (histogram instanceof DoubleHistogram) {

111

DoubleHistogram doubleHistogram = (DoubleHistogram) histogram;

112

System.out.printf("Double histogram: P95=%.3f%n",

113

doubleHistogram.getValueAtPercentile(95.0));

114

}

115

```

116

117

## Base64 String Encoding

118

119

### Base64 Compression and Encoding

120

121

```java

122

// Encode histogram as Base64 compressed string

123

public String encodeHistogramToBase64(AbstractHistogram histogram) {

124

int bufferSize = histogram.getNeededByteBufferCapacity();

125

ByteBuffer buffer = ByteBuffer.allocate(bufferSize);

126

127

// Encode with maximum compression

128

int compressedSize = histogram.encodeIntoCompressedByteBuffer(buffer, 9);

129

130

// Extract compressed bytes

131

buffer.flip();

132

byte[] compressedBytes = new byte[compressedSize];

133

buffer.get(compressedBytes);

134

135

// Convert to Base64

136

return Base64Helper.printBase64Binary(compressedBytes);

137

}

138

139

// Decode histogram from Base64 string

140

public Histogram decodeHistogramFromBase64(String base64String) {

141

// Parse Base64 to bytes

142

byte[] compressedBytes = Base64Helper.parseBase64Binary(base64String);

143

144

// Create buffer and decode

145

ByteBuffer buffer = ByteBuffer.wrap(compressedBytes);

146

return Histogram.decodeFromCompressedByteBuffer(buffer, 1000);

147

}

148

```

149

150

### Convenient String Serialization

151

152

```java

153

// Using built-in string serialization

154

Histogram histogram = createSampleHistogram();

155

156

// Encode to compressed byte buffer, then Base64

157

int bufferSize = histogram.getNeededByteBufferCapacity();

158

ByteBuffer buffer = ByteBuffer.allocate(bufferSize);

159

int compressedSize = histogram.encodeIntoCompressedByteBuffer(buffer, 9);

160

161

buffer.flip();

162

byte[] compressedBytes = new byte[compressedSize];

163

buffer.get(compressedBytes);

164

String encoded = Base64Helper.printBase64Binary(compressedBytes);

165

166

System.out.println("Encoded histogram: " + encoded);

167

168

// Direct decoding from string

169

Histogram restored = Histogram.fromString(encoded);

170

171

// Verify restoration

172

System.out.printf("Original: count=%d, P95=%d%n",

173

histogram.getTotalCount(), histogram.getValueAtPercentile(95.0));

174

System.out.printf("Restored: count=%d, P95=%d%n",

175

restored.getTotalCount(), restored.getValueAtPercentile(95.0));

176

```

177

178

## Histogram Log Processing

179

180

### HistogramLogWriter

181

182

Class for writing histograms to log files in standard format.

183

184

```java { .api }

185

public class HistogramLogWriter {

186

187

// Constructors

188

public HistogramLogWriter(String fileName) throws FileNotFoundException;

189

public HistogramLogWriter(File outputFile) throws FileNotFoundException;

190

public HistogramLogWriter(PrintStream outputStream);

191

192

// Writing methods

193

void outputComment(String comment);

194

void outputLegend();

195

void outputStartTime(long startTime);

196

void outputBaseTime(long baseTime);

197

void outputIntervalHistogram(EncodableHistogram histogram);

198

199

// Utility methods

200

void close();

201

}

202

```

203

204

### Writing Histogram Logs

205

206

```java

207

// Create log writer

208

try (FileOutputStream fos = new FileOutputStream("performance.hlog");

209

PrintStream ps = new PrintStream(fos)) {

210

211

HistogramLogWriter logWriter = new HistogramLogWriter(ps);

212

213

// Write log header

214

logWriter.outputComment("Performance measurement log");

215

logWriter.outputComment("Application: MyService v1.2.3");

216

logWriter.outputStartTime(System.currentTimeMillis());

217

logWriter.outputLegend();

218

219

// Simulate interval recording

220

Recorder recorder = new Recorder(3);

221

long startTime = System.currentTimeMillis();

222

223

for (int interval = 0; interval < 60; interval++) { // 60 intervals

224

// Simulate load for 1 second

225

simulateLoad(recorder, 1000);

226

227

// Get interval histogram

228

Histogram intervalHist = recorder.getIntervalHistogram();

229

230

// Set timestamps for this interval

231

long endTime = System.currentTimeMillis();

232

intervalHist.setStartTimeStamp(startTime);

233

intervalHist.setEndTimeStamp(endTime);

234

intervalHist.setTag("interval-" + interval);

235

236

// Write to log

237

logWriter.outputIntervalHistogram(intervalHist);

238

239

startTime = endTime;

240

}

241

242

logWriter.outputComment("Log completed successfully");

243

}

244

```

245

246

### HistogramLogReader

247

248

Class for reading histogram logs and processing interval data.

249

250

```java { .api }

251

public class HistogramLogReader implements Iterable<EncodableHistogram> {

252

253

// Constructors

254

public HistogramLogReader(String fileName) throws FileNotFoundException;

255

public HistogramLogReader(File inputFile) throws FileNotFoundException;

256

public HistogramLogReader(InputStream inputStream);

257

258

// Reading methods

259

boolean hasNext();

260

EncodableHistogram nextIntervalHistogram();

261

EncodableHistogram nextIntervalHistogram(double startTimeSec, double endTimeSec);

262

263

// Iterator support

264

Iterator<EncodableHistogram> iterator();

265

266

// Utility methods

267

void close();

268

}

269

```

270

271

### Reading and Processing Histogram Logs

272

273

```java

274

// Read histogram log file

275

try (HistogramLogReader logReader = new HistogramLogReader("performance.hlog")) {

276

277

System.out.println("Processing histogram log...");

278

279

long totalSamples = 0;

280

double maxP99 = 0;

281

List<Double> p95Values = new ArrayList<>();

282

283

// Process each interval histogram

284

for (EncodableHistogram histogram : logReader) {

285

if (histogram instanceof Histogram) {

286

Histogram intHist = (Histogram) histogram;

287

288

totalSamples += intHist.getTotalCount();

289

long p95 = intHist.getValueAtPercentile(95.0);

290

long p99 = intHist.getValueAtPercentile(99.0);

291

292

p95Values.add((double) p95);

293

maxP99 = Math.max(maxP99, p99);

294

295

System.out.printf("Interval %s: count=%d, P95=%d, P99=%d%n",

296

intHist.getTag(), intHist.getTotalCount(), p95, p99);

297

}

298

}

299

300

// Generate summary statistics

301

double avgP95 = p95Values.stream().mapToDouble(Double::doubleValue).average().orElse(0);

302

303

System.out.printf("Summary:%n");

304

System.out.printf(" Total samples: %d%n", totalSamples);

305

System.out.printf(" Average P95: %.1f%n", avgP95);

306

System.out.printf(" Maximum P99: %.1f%n", maxP99);

307

}

308

```

309

310

### Time-Range Filtering

311

312

```java

313

// Read histograms within specific time range

314

try (HistogramLogReader logReader = new HistogramLogReader("performance.hlog")) {

315

316

// Define time range (seconds since epoch)

317

double startTime = System.currentTimeMillis() / 1000.0 - 3600; // Last hour

318

double endTime = System.currentTimeMillis() / 1000.0;

319

320

System.out.printf("Analyzing histograms from %.0f to %.0f%n", startTime, endTime);

321

322

EncodableHistogram histogram;

323

while ((histogram = logReader.nextIntervalHistogram(startTime, endTime)) != null) {

324

System.out.printf("Processing histogram: %s (start=%.0f, end=%.0f)%n",

325

histogram.getTag(),

326

histogram.getStartTimeStamp() / 1000.0,

327

histogram.getEndTimeStamp() / 1000.0);

328

329

analyzeHistogram(histogram);

330

}

331

}

332

```

333

334

## Advanced Log Processing

335

336

### HistogramLogProcessor

337

338

Configurable processor for advanced log analysis and transformation.

339

340

```java { .api }

341

public class HistogramLogProcessor {

342

343

// Constructor

344

public HistogramLogProcessor();

345

346

// Event handler interfaces

347

interface EventHandler {

348

void handleHistogramInterval(EncodableHistogram histogram);

349

}

350

351

// Processing methods

352

void processLogFile(String inputFileName, EventHandler handler);

353

void processLogFile(File inputFile, EventHandler handler);

354

}

355

```

356

357

### Custom Log Processing

358

359

```java

360

// Custom histogram log processor

361

HistogramLogProcessor processor = new HistogramLogProcessor();

362

363

// Define custom processing logic

364

HistogramLogProcessor.EventHandler customHandler = histogram -> {

365

if (histogram instanceof Histogram) {

366

Histogram h = (Histogram) histogram;

367

368

// Custom analysis logic

369

long p99 = h.getValueAtPercentile(99.0);

370

if (p99 > 10000) { // Alert if P99 > 10ms

371

System.err.printf("ALERT: High P99 latency %d μs in interval %s%n",

372

p99, h.getTag());

373

}

374

375

// Custom metrics extraction

376

extractCustomMetrics(h);

377

}

378

};

379

380

// Process log with custom handler

381

processor.processLogFile("performance.hlog", customHandler);

382

```

383

384

### Log Aggregation and Analysis

385

386

```java

387

public class HistogramLogAnalyzer {

388

389

public void analyzeLongTermTrends(String logFileName) {

390

Map<String, List<Long>> dailyP95s = new HashMap<>();

391

392

try (HistogramLogReader reader = new HistogramLogReader(logFileName)) {

393

for (EncodableHistogram histogram : reader) {

394

if (histogram instanceof Histogram) {

395

Histogram h = (Histogram) histogram;

396

397

// Extract date from timestamp

398

LocalDate date = Instant.ofEpochMilli(h.getStartTimeStamp())

399

.atZone(ZoneId.systemDefault()).toLocalDate();

400

String dateKey = date.toString();

401

402

// Collect P95 values by date

403

dailyP95s.computeIfAbsent(dateKey, k -> new ArrayList<>())

404

.add(h.getValueAtPercentile(95.0));

405

}

406

}

407

}

408

409

// Analyze daily trends

410

dailyP95s.entrySet().stream()

411

.sorted(Map.Entry.comparingByKey())

412

.forEach(entry -> {

413

String date = entry.getKey();

414

List<Long> p95s = entry.getValue();

415

416

double avgP95 = p95s.stream().mapToLong(Long::longValue).average().orElse(0);

417

long maxP95 = p95s.stream().mapToLong(Long::longValue).max().orElse(0);

418

419

System.out.printf("%s: avg=%.1f μs, max=%d μs, intervals=%d%n",

420

date, avgP95, maxP95, p95s.size());

421

});

422

}

423

424

public void detectAnomalies(String logFileName, double thresholdMultiplier) {

425

List<Double> p95Values = new ArrayList<>();

426

427

// First pass: collect all P95 values

428

try (HistogramLogReader reader = new HistogramLogReader(logFileName)) {

429

for (EncodableHistogram histogram : reader) {

430

if (histogram instanceof Histogram) {

431

Histogram h = (Histogram) histogram;

432

p95Values.add((double) h.getValueAtPercentile(95.0));

433

}

434

}

435

}

436

437

// Calculate baseline statistics

438

double mean = p95Values.stream().mapToDouble(Double::doubleValue).average().orElse(0);

439

double stdDev = calculateStandardDeviation(p95Values, mean);

440

double anomalyThreshold = mean + (thresholdMultiplier * stdDev);

441

442

System.out.printf("Anomaly detection: threshold=%.1f (mean=%.1f, stddev=%.1f)%n",

443

anomalyThreshold, mean, stdDev);

444

445

// Second pass: detect anomalies

446

try (HistogramLogReader reader = new HistogramLogReader(logFileName)) {

447

for (EncodableHistogram histogram : reader) {

448

if (histogram instanceof Histogram) {

449

Histogram h = (Histogram) histogram;

450

long p95 = h.getValueAtPercentile(95.0);

451

452

if (p95 > anomalyThreshold) {

453

System.out.printf("ANOMALY: %s P95=%d (%.1fx baseline)%n",

454

h.getTag(), p95, p95 / mean);

455

}

456

}

457

}

458

}

459

}

460

}

461

```

462

463

## Serialization Best Practices

464

465

### Metadata Management

466

467

```java

468

public void prepareHistogramForSerialization(EncodableHistogram histogram,

469

String tag,

470

long startTime,

471

long endTime) {

472

// Set comprehensive metadata

473

histogram.setTag(tag);

474

histogram.setStartTimeStamp(startTime);

475

histogram.setEndTimeStamp(endTime);

476

477

System.out.printf("Prepared histogram for serialization:%n");

478

System.out.printf(" Tag: %s%n", histogram.getTag());

479

System.out.printf(" Time range: %d - %d (%d ms duration)%n",

480

startTime, endTime, endTime - startTime);

481

System.out.printf(" Max value: %.0f%n", histogram.getMaxValueAsDouble());

482

}

483

```

484

485

### Compression Level Optimization

486

487

```java

488

public void analyzeCompressionLevels(AbstractHistogram histogram) {

489

System.out.println("Compression Level Analysis:");

490

491

int uncompressedSize = histogram.getNeededByteBufferCapacity();

492

System.out.printf("Uncompressed: %d bytes%n", uncompressedSize);

493

494

for (int level = 0; level <= 9; level++) {

495

ByteBuffer buffer = ByteBuffer.allocate(uncompressedSize);

496

497

long startTime = System.nanoTime();

498

int compressedSize = histogram.encodeIntoCompressedByteBuffer(buffer, level);

499

long endTime = System.nanoTime();

500

501

double ratio = (double) compressedSize / uncompressedSize;

502

double timeMs = (endTime - startTime) / 1e6;

503

504

System.out.printf("Level %d: %d bytes (%.2f ratio) in %.2f ms%n",

505

level, compressedSize, ratio, timeMs);

506

}

507

}

508

```

509

510

### Batch Processing Optimization

511

512

```java

513

public class BatchHistogramProcessor {

514

515

public void processBatch(List<AbstractHistogram> histograms, String outputFile) {

516

try (FileOutputStream fos = new FileOutputStream(outputFile);

517

BufferedOutputStream bos = new BufferedOutputStream(fos, 65536);

518

PrintStream ps = new PrintStream(bos)) {

519

520

HistogramLogWriter writer = new HistogramLogWriter(ps);

521

522

// Write batch header

523

writer.outputComment("Batch processing: " + histograms.size() + " histograms");

524

writer.outputLegend();

525

526

// Process histograms with progress tracking

527

for (int i = 0; i < histograms.size(); i++) {

528

AbstractHistogram histogram = histograms.get(i);

529

530

// Set batch metadata

531

histogram.setTag("batch-" + i);

532

533

writer.outputIntervalHistogram(histogram);

534

535

// Progress reporting

536

if (i % 100 == 0) {

537

System.out.printf("Processed %d/%d histograms%n", i, histograms.size());

538

}

539

}

540

541

writer.outputComment("Batch processing completed");

542

543

} catch (IOException e) {

544

throw new RuntimeException("Failed to process batch", e);

545

}

546

}

547

}

548

```

549

550

## Memory-Efficient Serialization

551

552

### Streaming Serialization

553

554

```java

555

public class StreamingHistogramSerializer {

556

557

public void serializeStream(Iterator<AbstractHistogram> histograms,

558

OutputStream output) throws IOException {

559

560

try (BufferedOutputStream buffered = new BufferedOutputStream(output, 32768);

561

PrintStream ps = new PrintStream(buffered)) {

562

563

HistogramLogWriter writer = new HistogramLogWriter(ps);

564

writer.outputLegend();

565

566

while (histograms.hasNext()) {

567

AbstractHistogram histogram = histograms.next();

568

writer.outputIntervalHistogram(histogram);

569

570

// Force periodic flushing to manage memory

571

if (Math.random() < 0.01) { // 1% chance

572

ps.flush();

573

}

574

}

575

}

576

}

577

}

578

```

579

580

### Format Comparison

581

582

| Format | Size | Speed | Use Case |

583

|--------|------|-------|----------|

584

| Uncompressed Binary | Large | Fastest | Real-time systems |

585

| Compressed Binary (Level 1) | Medium | Fast | Network transmission |

586

| Compressed Binary (Level 6) | Small | Medium | Storage optimization |

587

| Compressed Binary (Level 9) | Smallest | Slow | Archive storage |

588

| Base64 Compressed | Small + Text | Medium | JSON/XML embedding |