Chapter 3 Experiment Results Summary

Experiment Configuration

ItemValue
PlatformmacOS (Apple Silicon), GCC/Clang, Release -O2
Buildcmake -DENABLE_MEM_STAT=ON -DBUILD_TEST=OFF
EncodingPLAIN (value columns) + PLAIN (timestamp, via global config override)
CompressionUNCOMPRESSED
Table modelAligned (shared timestamp via TimeChunkWriter)

Formula Constants (Aligned Mode)

SymbolFormulaDescription
$s_{data}$$8 + \sum \text{sizeof}(\text{field_type}_j)$Per-row data in ChunkWriter (shared timestamp)
$b$$n_{field} \times 104 + 96$Meta bytes per device per flush
$M_{init}$~900 KBFixed writer overhead

E3-2: Write Memory Formula Precision

Goal: Validate that calculate_mem_size_for_all_group() matches $s_{data} \times F$.

Key Finding: Three Layers of Memory Measurement

LayerWhat it measuresExample (5000 rows, 1 DOUBLE field)
Formula ($s \times F$)Raw data bytes80,000 bytes (16 bytes/row)
Estimate APIEncoded data in ChunkWriter73,767 bytes (14.8 bytes/row)
ModStatActually allocated memory131,512 bytes (26.3 bytes/row)

With PLAIN+UNCOMPRESSED (1 DOUBLE field):

  • Estimate / Formula = 92% (close match, 8% overhead from page headers + statistics)
  • ModStat / Formula = 164% (ByteStream allocates in 64 KB pages)

With SNAPPY+TS_2DIFF (8 mixed fields, default encoding):

  • Formula overestimates by ~50% (by design: formula = upper bound)
  • INT32 PLAIN encoding uses write_var_int (variable-length), not fixed 4 bytes
  • Timestamp uses global TS_2DIFF encoding (not affected by per-column schema)

Write Precision Data (SNAPPY+TS_2DIFF, 8 fields)

batch_sizeDirect (KB)Formula (KB)Error
5,00013627350.1%
8,00021343751.2%
16,00015587582.2%
32,0008141,75053.5%
65,5361,6473,58454.0%

Conclusion: The formula gives a conservative upper bound. Direct monitoring gives the actual (post-encoding) value. This aligns with the thesis Section 3.5 design: formula for pre-planning, direct monitoring for runtime control.

Figures

  • F3_write_precision.pdf: Bar chart comparing formula vs direct estimate.

E3-2: Read Memory Formula Precision

Goal: Validate $M_{read} \approx M_{fixed} + \text{batch_size} \times s_{row} + N_{cols} \times C_{page}$.

Read Precision Data (PLAIN+UNCOMPRESSED)

N_colsbatch_sizePeak (KB)Formula (KB)Error
216,3841,0451,0242.1%
416,3841,3661,53611.1%
616,3841,7091,92011.0%
816,3842,3002,4325.4%
865,5366,9745,88818.5%

Best accuracy at batch_size=16384 (2%~11% error), consistent with the Page size (128 KB) being aligned with the batch data.

Figures

  • F3_read_precision.pdf: (Left) Peak memory vs batch_size by N_cols; (Right) Error % heatmap.

E3-4: EOQ Optimal Strategy Validation

Goal: Prove the U-shaped memory curve $M_{peak} = M_{init} + s \cdot F + K \cdot b$ and that minimum occurs at $F_{opt} = \sqrt{R \cdot D \cdot b / s}$.

Configuration

ParameterValue
D (devices)20
R (rows/device)2,000,000
n_field8 DOUBLE
s_data72 bytes/row
b928 bytes/device/flush
F_opt (formula)22,705 rows
M_min (formula)4.0 MB

Results: Sweeping F from F_opt/8 to F_opt*8

F/F_optFPeak (MB)Trend
0.122,83817.0M_meta dominates (too many flushes)
0.255,6768.7
0.5011,3524.6
1.0022,7053.3Near minimum
1.4132,1093.1Minimum
2.0045,4103.4
4.0090,8205.5
8.00181,64010.7M_data dominates (too few flushes)

The minimum occurs at F/F_opt = 1.0~1.4, confirming the EOQ model prediction.

  • Left side (F < F_opt): M_meta dominates, peak grows as 1/F.
  • Right side (F > F_opt): M_data dominates, peak grows as F.
  • The U-shape is symmetric on log scale, matching the EOQ theory.

Formula Constant Deviation Analysis

The measured minimum at F/F_opt ≈ 1.4 rather than exactly 1.0 is explained by the formula constants' deviation from actual values:

ConstantFormula ValueMeasured Ratio (actual/formula)Source of deviation
$s$ (data/row)72 bytes×0.92 (formula overestimates 8%)Page header + statistics overhead amortized over rows
$b$ (meta/flush)928 bytes×1.36 (formula underestimates 36%)Object headers, pointer overhead, allocator alignment

Per-F detailed measurements:

F/F_optFs ratiob ratioPeak (MB)
0.122,8381.0271.34716.95
0.5011,3520.7611.3534.58
1.0022,7050.9431.3613.28
1.4132,1090.9261.3673.13
2.0045,4100.9081.3763.36
8.00181,6400.8561.47110.67

Correcting for the actual constants:

$$F_{opt,corrected} = \sqrt{\frac{b_{actual}}{s_{actual}}} \times F_{opt} = \sqrt{\frac{1.36}{0.92}} \times F_{opt} \approx 1.22 \times F_{opt}$$

The corrected theoretical optimum (1.22×) is close to the measured minimum (1.4×). The remaining gap is within the flat bottom of the U-curve: peak memory between F/F_opt = 1.0 and 2.0 differs by only 6% (3.13 MB vs 3.28 MB at 1.0×, 3.36 MB at 2.0×), making the exact position of the minimum practically insignificant.

Key takeaway: The formula parameter $b$ underestimates actual meta overhead by ~35% due to memory allocator alignment and object management overhead beyond the serialization size. This causes the actual optimal $F$ to shift rightward (fewer flushes needed). Since the formula yields a conservative $F_{opt}$ (slightly smaller than actual optimal), it is safe for pre-planning: the system flushes slightly more often than necessary, which is preferable to flushing too infrequently and risking memory overflow.

Figures

  • F3_eoq_ushape.pdf: U-shape curve with measured peak, formula curve, and M_data/M_meta decomposition.

E3-4: Memory Budget Compliance (Two-Level Control)

Goal: Validate that MemConstrainedWriter keeps memory within budget and triggers file rotation when meta accumulates.

Configuration

  • Schema: 8 mixed fields (PLAIN+UNCOMPRESSED), 10 devices, 50M total rows
  • Timestamp: PLAIN + UNCOMPRESSED (global config override)
  • Control: Direct monitoring (calculate_mem_size_for_all_group + calculate_meta_mem_size)
  • Budget split: 50/50 between data and meta
  • batch_cap: 4096 rows (to reduce overshoot at data_budget boundary)

Results

M_limitpeak_totalWithin budget?FlushesRotationsFilesThroughput
2 MB1.16 MBOK2441561.77 M/s
4 MB2.71 MBOK918011.69 M/s
8 MB4.14 MBOK409011.72 M/s
16 MB7.90 MBOK194011.94 M/s
32 MB15.79 MBOK95012.01 M/s

Key Observations

  1. Memory constraint satisfied: peak_total never exceeds M_limit in all configurations. The two-level control (flush for M_data + rotation for M_meta) works correctly.

  2. File rotation triggered at 2 MB: With only 0.6 MB meta budget, the accumulated meta (~1.3 KB/flush) triggers rotation after approximately 420 flushes per file. 50M rows across 6 files = ~8.3M rows/file, demonstrating continuous writing across file boundaries.

  3. Data budget overshoot: At 2 and 4 MB, peak_data slightly exceeds data_budget (1.2~1.3x) because flush is checked after each batch write (4096 rows ≈ 230 KB per batch). This batch-granularity overshoot is bounded and does not cause total memory to exceed M_limit since the meta budget absorbs the slack.

  4. Throughput vs budget: Throughput degrades slightly at very small budgets (1.77 M/s at 2 MB vs 2.01 M/s at 32 MB) due to frequent flush I/O overhead. The degradation is modest (~12%) even with a 16x budget reduction.

  5. Flush count scales inversely: Flush count approximately halves when budget doubles (2441 → 918 → 409 → 194 → 95), consistent with $F \propto M_{avail}$.

Figures

  • F3_write_budget.pdf: Bar chart (throughput) + line (flush count) vs memory budget.

Key Conclusions

  1. Formula accuracy (PLAIN+UNCOMPRESSED): With no encoding/compression and aligned timestamp, Estimate API matches formula within ~8%. Remaining gap comes from page headers and statistics overhead.

  2. Formula as conservative upper bound (with encoding): With SNAPPY+TS_2DIFF, formula overestimates $M_{data}$ by ~50%, which is by design. Direct monitoring provides exact runtime control. The thesis's two-tier design (formula for pre-planning, direct monitoring for runtime) is validated.

  3. EOQ U-shape confirmed: The measured peak memory curve matches the theoretical U-shape. Minimum occurs at F/F_opt ≈ 1.0~1.4, close to the formula prediction. The shift is explained by $b$ being underestimated by ~35% (allocator alignment and object overhead beyond serialization size). After correcting $b$, the theoretical optimum is at 1.22× F_opt, consistent with the measurement.

  4. Flat optimum region: Peak memory between F/F_opt = 1.0 and 2.0 differs by only 6%, meaning the exact value of F has little practical impact near the optimum. The formula's conservative F_opt (slightly smaller than actual) is safe: the system flushes slightly more often than necessary, avoiding memory overflow.

  5. Two-level control works: Direct monitoring achieves stable throughput (2.0 M rows/s) across memory budgets (8128 MB). Flush frequency inversely proportional to budget ($F \propto M_{avail}$). No file rotation triggered at 20M rows.

  6. Aligned mode formula: For aligned tables, $s_{data} = 8 + \sum \text{sizeof}(\text{field_type}j)$ (shared timestamp), differing from non-aligned $s{data} = \sum (8 + \text{sizeof}(\text{field_type}_j))$ by ~2x in the timestamp component.

  7. Three layers of memory measurement: Formula ($s \times F$, upper bound) > Estimate API (encoded actual, for runtime control) > formula with actual encoding. ModStat allocation (includes ByteStream page granularity at 64 KB) > all of the above. Each layer serves a different purpose.