cton 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0295922a011dd898278f9f57de2f48f2acbe0ce3363f263f4e2b2753993ebdea'
4
- data.tar.gz: 33bb13ee23584ff6cd51bf6bc6c1a869d02f206ff0792a172c9aa7cdc5547977
3
+ metadata.gz: 1c9161ae830ba6b01d3ec94d1170fc4295aaacfa839c869aaa6adefe2711cc2d
4
+ data.tar.gz: 80c4ba30abbf8a562bde581f26e7dc5529aa46275b61930fe28370f34156db61
5
5
  SHA512:
6
- metadata.gz: 9dff47df67680eabf6fb7ac05dac606e969df0a0d31d575318fa4a72c51c8fe85d38b671f4e2b8b8caa0e969184c044e06547b135b9a5b5b0baa4c3e28232322
7
- data.tar.gz: be363392d2305b6940e46060310a908922bbf822ae487e9d4b20441e4cc51e5e8161332cd5d8c0846743663d1251ff7b1b5480f21f36f9b52c0aafb0404f4b74
6
+ metadata.gz: 914196284081bacd5b7f5f6ac9a1b246ea8924eddbb26cd28796b12a2ee2156718a9ff3b795b86188d483da4fc294b002a93e935815f692b432dac78b5304dcf
7
+ data.tar.gz: d9b1bfb1f7de402fe9de0d7da90f750d490dbdcb4e572e9283bc3ed15b1b43e3f3f9b44a4031f80ecf5d610a73d64719f3c78f170060de78035e04dab3a9d663
data/CHANGELOG.md CHANGED
@@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.3.0] - 2025-11-20
9
+
10
+ ### Added
11
+
12
+ - **Performance tunables**: `Cton.dump` now accepts `decimal_mode: :fast | :precise`, allowing callers to trade float-format determinism for lower allocation pressure. Specs cover both modes.
13
+ - **Benchmark harness**: New `bench/encode_decode_bench.rb` script (wired into the README/Development docs) exercises encode/decode hot paths and prints comparative JSON vs CTON timings. On Ruby 3.1.4/macOS the fast encoder completes 1,000 iterations in ~0.63s and the new inline decoder stress test wraps 400 concatenated documents in ~4.14s.
14
+ - **Regression tests**: Added specs for streaming documents without separators plus validation around the new decimal mode toggle.
15
+
16
+ ### Changed
17
+
18
+ - **Encoder**: Memoizes table schemas per array instance, adds a fast-path for homogeneous scalar lists, and reduces float/BigDecimal copying by favoring Ruby's native float formatting before falling back to `BigDecimal`. Unsupported `decimal_mode` values now raise immediately.
19
+ - **Decoder**: Replaces high-allocation `StringScanner` tokenization with raw string slicing, improves key-boundary detection for inline payloads, and keeps symbolization logic untouched. Boundary heuristics now prefer alphabetic key starts to avoid splitting numeric payloads.
20
+ - **Documentation**: README now calls out the tuning flags, inline caveats, and benchmark instructions; Development workflow highlights how to rerun the perf suite.
21
+
22
+ ### Fixed
23
+
24
+ - **Inline parsing**: Eliminated the runaway allocations and incorrect key splits when processing long documents with `separator: ""`.
25
+ - **Float normalization**: Restored canonical `9.2`-style output in fast mode while keeping the new perf optimizations.
26
+
27
+ ## [0.2.0] - 2025-11-19
28
+
29
+ ### Added
30
+
31
+ - **CLI Tool**: New `bin/cton` executable for converting between JSON and CTON from the command line. Supports auto-detection, pretty printing, and file I/O.
32
+ - **Streaming IO**: `Cton.dump` now accepts an `IO` object as the second argument (or via `io:` keyword), allowing direct writing to files or sockets without intermediate string allocation.
33
+ - **Pretty Printing**: Added `pretty: true` option to `Cton.dump` to format output with indentation and newlines for better readability.
34
+ - **Extended Types**: Native support for `Time`, `Date` (ISO8601), `Set` (as Array), and `OpenStruct` (as Object).
35
+ - **Enhanced Error Reporting**: `ParseError` now includes line and column numbers to help locate syntax errors in large documents.
36
+
37
+ ### Changed
38
+
39
+ - **Ruby 3 Compatibility**: Improved argument handling in `Cton.dump` to robustly support Ruby 3 keyword arguments when passing hashes.
40
+
8
41
  ## [0.1.1] - 2025-11-18
9
42
 
10
43
  ### Changed
data/README.md CHANGED
@@ -1,32 +1,115 @@
1
1
  # CTON
2
2
 
3
- CTON (Compact Token-Oriented Notation) is an aggressively minified, JSON-compatible wire format that keeps prompts short without giving up schema hints. It is shape-preserving (objects, arrays, scalars, table-like arrays) and deterministic, so you can safely round-trip between Ruby hashes and compact strings that work well in LLM prompts.
3
+ [![Gem Version](https://badge.fury.io/rb/cton.svg)](https://badge.fury.io/rb/cton)
4
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/davidesantangelo/cton/blob/master/LICENSE.txt)
5
+
6
+ **CTON** (Compact Token-Oriented Notation) is an aggressively minified, JSON-compatible wire format that keeps prompts short without giving up schema hints. It is shape-preserving (objects, arrays, scalars, table-like arrays) and deterministic, so you can safely round-trip between Ruby hashes and compact strings that work well in LLM prompts.
7
+
8
+ ---
9
+
10
+ ## 📖 Table of Contents
11
+
12
+ - [What is CTON?](#what-is-cton)
13
+ - [Why another format?](#why-another-format)
14
+ - [Examples](#examples)
15
+ - [Token Savings](#token-savings-vs-json--toon)
16
+ - [Installation](#installation)
17
+ - [Usage](#usage)
18
+ - [Performance & Benchmarks](#performance--benchmarks)
19
+ - [Teaching CTON to LLMs](#teaching-cton-to-llms)
20
+ - [Development](#development)
21
+ - [Contributing](#contributing)
22
+ - [License](#license)
23
+
24
+ ---
25
+
26
+ ## What is CTON?
27
+
28
+ CTON is designed to be the most efficient way to represent structured data for Large Language Models (LLMs). It strips away the "syntactic sugar" of JSON that humans like (indentation, excessive quoting, braces) but machines don't strictly need, while adding "structural hints" that help LLMs generate valid output.
29
+
30
+ ### Key Concepts
31
+
32
+ 1. **Root is Implicit**: No curly braces `{}` wrapping the entire document.
33
+ 2. **Minimal Punctuation**:
34
+ * Objects use `key=value`.
35
+ * Nested objects use parentheses `(key=value)`.
36
+ * Arrays use brackets with length `[N]=item1,item2`.
37
+ 3. **Table Compression**: If an array contains objects with the same keys, CTON automatically converts it into a table format `[N]{header1,header2}=val1,val2;val3,val4`. This is a massive token saver for datasets.
38
+
39
+ ---
40
+
41
+ ## Examples
42
+
43
+ ### Simple Key-Value Pairs
44
+
45
+ **JSON**
46
+ ```json
47
+ {
48
+ "task": "planning",
49
+ "urgent": true,
50
+ "id": 123
51
+ }
52
+ ```
53
+
54
+ **CTON**
55
+ ```text
56
+ task=planning,urgent=true,id=123
57
+ ```
58
+
59
+ ### Nested Objects
60
+
61
+ **JSON**
62
+ ```json
63
+ {
64
+ "user": {
65
+ "name": "Davide",
66
+ "settings": {
67
+ "theme": "dark"
68
+ }
69
+ }
70
+ }
71
+ ```
72
+
73
+ **CTON**
74
+ ```text
75
+ user(name=Davide,settings(theme=dark))
76
+ ```
77
+
78
+ ### Arrays and Tables
79
+
80
+ **JSON**
81
+ ```json
82
+ {
83
+ "tags": ["ruby", "gem", "llm"],
84
+ "files": [
85
+ { "name": "README.md", "size": 1024 },
86
+ { "name": "lib/cton.rb", "size": 2048 }
87
+ ]
88
+ }
89
+ ```
90
+
91
+ **CTON**
92
+ ```text
93
+ tags[3]=ruby,gem,llm
94
+ files[2]{name,size}=README.md,1024;lib/cton.rb,2048
95
+ ```
96
+
97
+ ---
4
98
 
5
99
  ## Why another format?
6
100
 
7
101
  - **Less noise than YAML/JSON**: no indentation, no braces around the root, and optional quoting.
8
102
  - **Schema guardrails**: arrays carry their length (`friends[3]`) and table headers (`{id,name,...}`) so downstream parsing can verify shape.
9
103
  - **LLM-friendly**: works as a single string you can embed in a prompt together with short parsing instructions.
10
- - **Token savings**: CTON compounds the JSON → TOON savings; see the section below for concrete numbers.
104
+ - **Token savings**: CTON compounds the JSON → TOON savings.
11
105
 
12
- ## Token savings vs JSON & TOON
106
+ ### Token savings vs JSON & TOON
13
107
 
14
108
  - **JSON → TOON**: The [TOON benchmarks](https://toonformat.dev) report roughly 40% fewer tokens than plain JSON on mixed-structure prompts while retaining accuracy due to explicit array lengths and headers.
15
- - **TOON → CTON**: By stripping indentation and forcing everything inline, CTON cuts another ~20–40% of characters. The sample above is ~350 characters as TOON and ~250 as CTON (~29% fewer), and larger tabular datasets show similar reductions.
16
- - **Net effect**: In practice you can often reclaim 50–60% of the token budget versus raw JSON, leaving more room for instructions or reasoning steps while keeping a deterministic schema.
109
+ - **TOON → CTON**: By stripping indentation and forcing everything inline, CTON cuts another ~20–40% of characters.
110
+ - **Net effect**: In practice you can often reclaim **50–60% of the token budget** versus raw JSON, leaving more room for instructions or reasoning steps while keeping a deterministic schema.
17
111
 
18
- ## Format at a glance
19
-
20
- ```
21
- context(task="Our favorite hikes together",location=Boulder,season=spring_2025)
22
- friends[3]=ana,luis,sam
23
- hikes[3]{id,name,distanceKm,elevationGain,companion,wasSunny}=1,"Blue Lake Trail",7.5,320,ana,true;2,"Ridge Overlook",9.2,540,luis,false;3,"Wildflower Loop",5.1,180,sam,true
24
- ```
25
-
26
- - Objects use parentheses and `key=value` pairs separated by commas.
27
- - Arrays encode their length: `[N]=...`. When every element is a flat hash with the same keys, they collapse into a compact table: `[N]{key1,key2}=row1;row2`.
28
- - Scalars (numbers, booleans, `null`) keep their JSON text. Strings only need quotes when they contain whitespace or reserved punctuation.
29
- - For parsing safety the Ruby encoder inserts a single `\n` between top-level segments. You can override this if you truly need a fully inline document (see options below).
112
+ ---
30
113
 
31
114
  ## Installation
32
115
 
@@ -42,28 +125,32 @@ Or install it directly:
42
125
  gem install cton
43
126
  ```
44
127
 
128
+ ---
129
+
45
130
  ## Usage
46
131
 
47
132
  ```ruby
48
133
  require "cton"
49
134
 
50
135
  payload = {
51
- "context" => {
52
- "task" => "Our favorite hikes together",
53
- "location" => "Boulder",
54
- "season" => "spring_2025"
55
- },
56
- "friends" => %w[ana luis sam],
57
- "hikes" => [
58
- { "id" => 1, "name" => "Blue Lake Trail", "distanceKm" => 7.5, "elevationGain" => 320, "companion" => "ana", "wasSunny" => true },
59
- { "id" => 2, "name" => "Ridge Overlook", "distanceKm" => 9.2, "elevationGain" => 540, "companion" => "luis", "wasSunny" => false },
60
- { "id" => 3, "name" => "Wildflower Loop", "distanceKm" => 5.1, "elevationGain" => 180, "companion" => "sam", "wasSunny" => true }
61
- ]
136
+ "context" => {
137
+ "task" => "Our favorite hikes together",
138
+ "location" => "Boulder",
139
+ "season" => "spring_2025"
140
+ },
141
+ "friends" => %w[ana luis sam],
142
+ "hikes" => [
143
+ { "id" => 1, "name" => "Blue Lake Trail", "distanceKm" => 7.5, "elevationGain" => 320, "companion" => "ana", "wasSunny" => true },
144
+ { "id" => 2, "name" => "Ridge Overlook", "distanceKm" => 9.2, "elevationGain" => 540, "companion" => "luis", "wasSunny" => false },
145
+ { "id" => 3, "name" => "Wildflower Loop", "distanceKm" => 5.1, "elevationGain" => 180, "companion" => "sam", "wasSunny" => true }
146
+ ]
62
147
  }
63
148
 
149
+ # Encode to CTON
64
150
  cton = Cton.dump(payload)
65
151
  # => "context(... )\nfriends[3]=ana,luis,sam\nhikes[3]{...}"
66
152
 
153
+ # Decode back to Hash
67
154
  round_tripped = Cton.load(cton)
68
155
  # => original hash
69
156
 
@@ -72,24 +159,159 @@ symbolized = Cton.load(cton, symbolize_names: true)
72
159
 
73
160
  # Want a truly inline document? Opt in explicitly (decoding becomes unsafe for ambiguous cases).
74
161
  inline = Cton.dump(payload, separator: "")
162
+
163
+ # Pretty print for human readability
164
+ pretty = Cton.dump(payload, pretty: true)
165
+
166
+ # Stream to an IO object (file, socket, etc.)
167
+ File.open("data.cton", "w") do |f|
168
+ Cton.dump(payload, f)
169
+ end
170
+
171
+ # Toggle float normalization strategies
172
+ fast = Cton.dump(payload) # default :fast mode
173
+ strict = Cton.dump(payload, decimal_mode: :precise)
75
174
  ```
76
175
 
77
- ### Table detection
176
+ ### CLI Tool
78
177
 
79
- Whenever an array is made of hashes that all expose the same scalar keys, the encoder flattens it into a table to save tokens. Mixed or nested arrays fall back to `[N]=(value1,value2,...)`.
178
+ CTON comes with a command-line tool for quick conversions:
80
179
 
81
- ### Separators & ambiguity
180
+ ```bash
181
+ # Convert JSON to CTON
182
+ echo '{"hello": "world"}' | cton
183
+ # => hello=world
82
184
 
83
- Removing every newline makes certain inputs ambiguous because `sam` and the next key `hikes` can merge into `samhikes`. The default `separator: "\n"` avoids that by inserting a single newline between root segments. You may pass `separator: ""` to `Cton.dump` for maximum compactness, but decoding such strings is only safe if you can guarantee extra quoting or whitespace between segments.
185
+ # Convert CTON to JSON
186
+ echo 'hello=world' | cton --to-json
187
+ # => {"hello":"world"}
84
188
 
85
- ### Literal safety & number normalization
189
+ # Pretty print
190
+ cton --pretty input.json
191
+ ```
86
192
 
87
- Following the TOON specification's guardrails, the encoder now:
193
+ ### Advanced Features
194
+
195
+ #### Extended Types
196
+ CTON natively supports serialization for:
197
+ - `Time` and `Date` (ISO8601 strings)
198
+ - `Set` (converted to Arrays)
199
+ - `OpenStruct` (converted to Objects)
200
+
201
+ #### Table detection
202
+ Whenever an array is made of hashes that all expose the same scalar keys, the encoder flattens it into a table to save tokens. Mixed or nested arrays fall back to `[N]=(value1,value2,...)`.
203
+
204
+ #### Separators & ambiguity
205
+ Removing every newline makes certain inputs ambiguous because `sam` and the next key `hikes` can merge into `samhikes`. The default `separator: "\n"` avoids that by inserting a single newline between root segments. You may pass `separator: ""` to `Cton.dump` for maximum compactness, but decoding such strings is only safe if you can guarantee extra quoting or whitespace between segments. When you intentionally omit separators, keep next-level keys alphabetic (e.g., `payload`, `k42`) so the decoder's boundary heuristic can split `...1payload...` without misclassifying numeric prefixes.
88
206
 
207
+ #### Literal safety & number normalization
208
+ Following the TOON specification's guardrails, the encoder now:
89
209
  - Auto-quotes strings that would otherwise be parsed as booleans, `null`, or numbers (e.g., `"true"`, `"007"`, `"1e6"`, `"-5"`) so they round-trip as strings without extra work.
90
210
  - Canonicalizes float/BigDecimal output: no exponent notation, no trailing zeros, and `-0` collapses to `0`.
91
211
  - Converts `NaN` and `±Infinity` inputs to `null`, matching TOON's normalization guidance so downstream decoders don't explode on non-finite numbers.
92
212
 
213
+ #### Decimal normalization modes
214
+ - `decimal_mode: :fast` (default) prefers Ruby's native float representation and only falls back to `BigDecimal` when scientific notation is detected, minimizing allocations on tight loops.
215
+ - `decimal_mode: :precise` forces the legacy `BigDecimal` path for every float, which is slower but useful for audit-grade dumps where you want deterministic decimal expansion.
216
+ - Both modes share the same trailing-zero stripping and `-0 → 0` normalization, so switching modes never affects integer formatting.
217
+
218
+ ---
219
+
220
+ ## Performance & Benchmarks
221
+
222
+ CTON focuses on throughput: encoder table schemas are memoized, scalar list encoding keeps a reusable buffer, floats avoid `BigDecimal` when they can, and the decoder slices straight from the raw string to sidestep `StringScanner` allocations. You can reproduce the numbers below with the bundled script:
223
+
224
+ ```bash
225
+ bundle exec ruby bench/encode_decode_bench.rb
226
+ # customize input size / iterations
227
+ ITERATIONS=2000 STREAM_SIZE=400 bundle exec ruby bench/encode_decode_bench.rb
228
+ ```
229
+
230
+ Latest results on Ruby 3.1.4/macOS (M-series), 1,000 iterations, `STREAM_SIZE=200`:
231
+
232
+ | Benchmark | Time (s) |
233
+ | --- | --- |
234
+ | `cton dump` (:fast) | 0.626 |
235
+ | `cton dump` (:precise) | 0.658 |
236
+ | `json generate` | 0.027 |
237
+ | `cton load` | 2.067 |
238
+ | `json parse` | 0.045 |
239
+ | `cton inline load` (separator=`""`, double payload) | 4.140 |
240
+
241
+ `cton inline load` deliberately concatenates documents without separators to stress the new boundary detector; it now finishes without the runaway allocations seen in earlier releases.
242
+
243
+ ---
244
+
245
+ ## Teaching CTON to LLMs
246
+
247
+ Use this system prompt to teach an LLM how to understand and generate CTON:
248
+
249
+ ````markdown
250
+ You are an expert in data serialization and specifically in CTON (Compact Token-Oriented Notation). CTON is a token-efficient data format optimized for LLMs that serves as a compact alternative to JSON.
251
+
252
+ Your task is to interpret CTON input and convert it to JSON, or convert JSON input into valid CTON format, following the specification below.
253
+
254
+ ### CTON Specification
255
+
256
+ CTON minimizes syntax characters (braces, quotes) while preserving structure and type safety.
257
+
258
+ **1. Basic Structure (Key-Value)**
259
+ - **Rule:** Do not use outer curly braces `{}` for the root object.
260
+ - **Rule:** Use `=` to separate keys and values.
261
+ - **Rule:** Use `,` to separate fields.
262
+ - **Rule:** Do not use quotes around "safe" strings (alphanumeric, simple text).
263
+ - **Example:** - JSON: `{"task": "planning", "urgent": true}`
264
+ - CTON: `task=planning,urgent=true`
265
+
266
+ **2. Nested Objects**
267
+ - **Rule:** Use parentheses `()` to denote a nested object instead of `{}`.
268
+ - **Example:**
269
+ - JSON: `{"context": {"user": "Davide", "theme": "dark"}}`
270
+ - CTON: `context(user=Davide,theme=dark)`
271
+
272
+ **3. Arrays of Objects (Table Compression)**
273
+ - **Rule:** Use the syntax `key[count]{columns}=values` for arrays of objects to avoid repeating keys.
274
+ - **Structure:** `key[Length]{col1,col2}=val1,val2;val1,val2`
275
+ - **Details:** - `[N]` denotes the number of items in the array.
276
+ - `{col1,col2}` defines the schema headers.
277
+ - `;` separates distinct objects (rows).
278
+ - `,` separates values within an object.
279
+ - **Example:**
280
+
281
+ JSON:
282
+ ```json
283
+ {
284
+ "files": [
285
+ { "name": "README.md", "size": 1024 },
286
+ { "name": "lib.rb", "size": 2048 }
287
+ ]
288
+ }
289
+ ```
290
+
291
+ CTON: `files[2]{name,size}=README.md,1024;lib.rb,2048`
292
+
293
+ **4. Type Safety & Literals**
294
+ - **Booleans/Null:** `true`, `false`, and `null` are preserved as literals (unquoted).
295
+ - **Numbers:** Integers and floats are written as is (e.g., `1024`, `3.14`).
296
+ - **Escaping:** If a string value looks like a boolean, number, or contains reserved characters (like `,`, `;`, `=`, `(`, `)`), it must be wrapped in double quotes (e.g., `"true"`).
297
+
298
+ ### Examples for Training
299
+
300
+ **Input (JSON):**
301
+ ```json
302
+ {
303
+ "id": 123,
304
+ "active": true,
305
+ "metadata": {
306
+ "created_at": "2023-01-01",
307
+ "tags": "admin"
308
+ }
309
+ }
310
+ ```
311
+ ````
312
+
313
+ ---
314
+
93
315
  ## Type Safety
94
316
 
95
317
  CTON ships with RBS signatures (`sig/cton.rbs`) to support type checking and IDE autocompletion.
@@ -100,6 +322,7 @@ CTON ships with RBS signatures (`sig/cton.rbs`) to support type checking and IDE
100
322
  bin/setup # install dependencies
101
323
  bundle exec rake # run tests and rubocop
102
324
  bin/console # interactive playground
325
+ bundle exec ruby bench/encode_decode_bench.rb # performance smoke test
103
326
  ```
104
327
 
105
328
  To release a new version, bump `Cton::VERSION` and run `bundle exec rake release`.
@@ -110,4 +333,4 @@ Bug reports and pull requests are welcome at https://github.com/davidesantangelo
110
333
 
111
334
  ## License
112
335
 
113
- MIT © Davide Santangelo
336
+ MIT © [Davide Santangelo](https://github.com/davidesantangelo)
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "benchmark"
5
+ require "json"
6
+ require_relative "../lib/cton"
7
+
8
+ ITERATIONS = Integer(ENV.fetch("ITERATIONS", 1_000))
9
+ STREAM_SIZE = Integer(ENV.fetch("STREAM_SIZE", 200))
10
+
11
+ sample_payload = {
12
+ "context" => {
13
+ "task" => "Our favorite hikes together",
14
+ "location" => "Boulder",
15
+ "season" => "spring_2025"
16
+ },
17
+ "friends" => %w[ana luis sam],
18
+ "hikes" => Array.new(STREAM_SIZE) do |idx|
19
+ {
20
+ "id" => idx + 1,
21
+ "name" => "Trail ##{idx + 1}",
22
+ "distanceKm" => (6.0 + ((idx % 5) * 0.5)),
23
+ "elevationGain" => 250 + ((idx % 3) * 50),
24
+ "companion" => %w[ana luis sam][idx % 3],
25
+ "wasSunny" => idx.even?
26
+ }
27
+ end
28
+ }
29
+
30
+ warm_cton = Cton.dump(sample_payload)
31
+ warm_json = JSON.generate(sample_payload)
32
+
33
+ puts "\nEncoding benchmarks (iterations=#{ITERATIONS}, stream_size=#{STREAM_SIZE})"
34
+ Benchmark.bm(25) do |bm|
35
+ bm.report("cton dump fast") do
36
+ ITERATIONS.times { Cton.dump(sample_payload) }
37
+ end
38
+
39
+ bm.report("cton dump precise") do
40
+ ITERATIONS.times { Cton.dump(sample_payload, decimal_mode: :precise) }
41
+ end
42
+
43
+ bm.report("json generate") do
44
+ ITERATIONS.times { JSON.generate(sample_payload) }
45
+ end
46
+ end
47
+
48
+ puts "\nDecoding benchmarks"
49
+ Benchmark.bm(25) do |bm|
50
+ bm.report("cton load") do
51
+ ITERATIONS.times { Cton.load(warm_cton) }
52
+ end
53
+
54
+ bm.report("json parse") do
55
+ ITERATIONS.times { JSON.parse(warm_json) }
56
+ end
57
+ end
58
+
59
+ puts "\nStreaming decode stress (#{STREAM_SIZE * 2} documents, separator=\"\")"
60
+ inline_blob = warm_cton.delete("\n") * 2
61
+ Benchmark.bm(25) do |bm|
62
+ bm.report("cton inline load") do
63
+ ITERATIONS.times { Cton.load(inline_blob) }
64
+ end
65
+ end