@zio.dev/zio-blocks 0.0.51 → 0.0.56

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.
Files changed (166) hide show
  1. package/adr/2026-07-18-data-migration.md +123 -0
  2. package/guides/async-getting-started.md +687 -0
  3. package/guides/compile-time-resource-safety-with-scope.md +6 -0
  4. package/guides/getting-started-with-mux.md +0 -112
  5. package/guides/query-dsl-extending.md +1 -1
  6. package/guides/query-dsl-fluent-builder.md +1 -1
  7. package/guides/query-dsl-reified-optics.md +1 -1
  8. package/guides/query-dsl-sql.md +395 -1
  9. package/guides/sql-checked-interpolation.md +173 -0
  10. package/guides/sql-transactions.md +286 -0
  11. package/guides/telemetry-guide.md +131 -70
  12. package/guides/zio-schema-migration.md +6 -6
  13. package/index.md +200 -559
  14. package/package.json +1 -1
  15. package/reference/async.md +1379 -531
  16. package/reference/chunk.md +3 -3
  17. package/reference/codegen/index.md +1 -1
  18. package/reference/combinators.md +4 -4
  19. package/reference/config/config-decoder.md +460 -0
  20. package/reference/config/config-source.md +489 -0
  21. package/reference/config/errors.md +278 -0
  22. package/reference/config/flags.md +369 -0
  23. package/reference/config/formats.md +314 -0
  24. package/reference/config/index.md +304 -0
  25. package/reference/config/rollout.md +336 -0
  26. package/reference/context.md +6 -49
  27. package/reference/data-migration.md +269 -0
  28. package/reference/datastar/attributes.md +302 -0
  29. package/reference/datastar/events.md +234 -0
  30. package/reference/datastar/index.md +256 -0
  31. package/reference/datastar/signals.md +230 -0
  32. package/reference/datastar/sse.md +295 -0
  33. package/reference/datastar.md +2 -2
  34. package/reference/docs.md +2 -2
  35. package/reference/endpoint/bulk-creation.md +96 -0
  36. package/reference/endpoint/endpoint.md +1 -0
  37. package/reference/endpoint/index.md +9 -89
  38. package/reference/endpoint/path-codec.md +12 -24
  39. package/reference/endpoint/route-pattern.md +4 -6
  40. package/reference/endpoint/segment-codec.md +19 -32
  41. package/reference/html.md +313 -9
  42. package/reference/htmx/index.md +4 -52
  43. package/reference/htmx/response-headers.md +240 -0
  44. package/reference/http-model/headers.md +735 -0
  45. package/reference/http-model/index.md +3 -1
  46. package/reference/http-model/model.md +107 -71
  47. package/reference/http-model/schema-codecs.md +522 -0
  48. package/reference/http-model/schema.md +6 -3
  49. package/reference/http-model/server-sent-event.md +341 -0
  50. package/reference/jwt.md +195 -0
  51. package/reference/maybe.md +128 -11
  52. package/reference/media-type.md +2 -2
  53. package/reference/mux.mdx +7 -2
  54. package/reference/openapi.md +3 -3
  55. package/reference/projection.md +654 -0
  56. package/reference/resource-management/index.md +1 -1
  57. package/reference/resource-management/resource.md +2 -98
  58. package/reference/resource-management/scope.md +1 -209
  59. package/reference/resource-management/wire.md +4 -50
  60. package/reference/ringbuffer/advanced.mdx +1 -1
  61. package/reference/ringbuffer/index.mdx +3 -3
  62. package/reference/ringbuffer/mpmc.mdx +38 -4
  63. package/reference/ringbuffer/mpsc.mdx +36 -4
  64. package/reference/ringbuffer/spmc.mdx +1 -1
  65. package/reference/ringbuffer/spsc.mdx +87 -15
  66. package/reference/schema/allows.md +0 -96
  67. package/reference/schema/binding.md +2 -2
  68. package/reference/schema/built-in-codecs/avro.md +2 -2
  69. package/reference/schema/built-in-codecs/bson.md +50 -20
  70. package/reference/schema/built-in-codecs/csv.md +2 -2
  71. package/reference/schema/built-in-codecs/index.md +3 -3
  72. package/reference/schema/built-in-codecs/json/index.md +2 -2
  73. package/reference/schema/built-in-codecs/json/json.md +1 -0
  74. package/reference/schema/built-in-codecs/messagepack.md +3 -3
  75. package/reference/schema/built-in-codecs/thrift.md +2 -2
  76. package/reference/schema/built-in-codecs/toon.md +3 -3
  77. package/reference/schema/built-in-codecs/yaml.md +2 -2
  78. package/reference/schema/codec.md +11 -11
  79. package/reference/schema/dynamic-optic.md +48 -3
  80. package/reference/schema/dynamic-schema.md +3 -3
  81. package/reference/schema/index.md +2 -0
  82. package/reference/schema/path-interpolator.md +2 -0
  83. package/reference/schema/reflect-transformer.md +140 -0
  84. package/reference/schema/schema-evolution/as.md +4 -4
  85. package/reference/schema/schema-evolution/into.md +2 -2
  86. package/reference/schema/schema-expr.md +2 -2
  87. package/reference/schema/schema-search.md +263 -0
  88. package/reference/schema/schema.md +10 -2
  89. package/reference/schema/type-class-derivation.md +1 -1
  90. package/reference/smithy.md +502 -3
  91. package/reference/sql/db-codec-deriver.md +3 -3
  92. package/reference/sql/db-codec.md +22 -22
  93. package/reference/sql/db-con.md +4 -4
  94. package/reference/sql/db-connection.md +1 -1
  95. package/reference/sql/db-param.md +1 -1
  96. package/reference/sql/db-result-reader.md +4 -2
  97. package/reference/sql/db-tx.md +46 -14
  98. package/reference/sql/ddl.md +1 -1
  99. package/reference/sql/frag.md +44 -10
  100. package/reference/sql/index.md +7 -7
  101. package/reference/sql/repo.md +15 -15
  102. package/reference/sql/sql-dialect.md +1 -1
  103. package/reference/sql/sql-logger.md +1 -1
  104. package/reference/sql/sql-name-mapper.md +3 -3
  105. package/reference/sql/table-metadata.md +3 -3
  106. package/reference/sql/table.md +10 -10
  107. package/reference/sql/transactor-zio.md +1 -1
  108. package/reference/sql/transactor.md +21 -11
  109. package/reference/sql-zio.md +2 -2
  110. package/reference/streams/core/index.md +32 -0
  111. package/reference/streams/{pipeline.md → core/pipeline.md} +210 -74
  112. package/reference/streams/{sink.md → core/sink.md} +331 -353
  113. package/reference/streams/{stream.md → core/stream.md} +919 -209
  114. package/reference/streams/execution-and-compatibility/async-execution.md +822 -0
  115. package/reference/streams/execution-and-compatibility/index.md +35 -0
  116. package/reference/streams/execution-and-compatibility/platform-differences.md +297 -0
  117. package/reference/streams/execution-and-compatibility/scala-2-compatibility.md +88 -0
  118. package/reference/streams/execution-and-compatibility/zero-boxing.md +393 -0
  119. package/reference/streams/index.md +140 -67
  120. package/reference/streams/primitives/index.md +30 -0
  121. package/reference/streams/primitives/reader.md +1992 -0
  122. package/reference/streams/{writer.md → primitives/writer.md} +254 -98
  123. package/reference/telemetry/common/any-value.md +90 -0
  124. package/reference/telemetry/common/attribute-key.md +87 -0
  125. package/reference/telemetry/common/attributes.md +118 -0
  126. package/reference/telemetry/common/index.md +39 -0
  127. package/reference/telemetry/common/instrumentation-scope.md +24 -0
  128. package/reference/telemetry/common/resource.md +34 -0
  129. package/reference/telemetry/index.md +311 -0
  130. package/reference/telemetry/logging/index.md +197 -0
  131. package/reference/telemetry/logging/log-enrichment.md +72 -0
  132. package/reference/telemetry/logging/log-formatter.md +100 -0
  133. package/reference/telemetry/logging/log-record-processor.md +56 -0
  134. package/reference/telemetry/logging/log-record.md +44 -0
  135. package/reference/telemetry/logging/log-writer.md +64 -0
  136. package/reference/telemetry/logging/logger-provider.md +142 -0
  137. package/reference/telemetry/logging/logger.md +83 -0
  138. package/reference/telemetry/logging/severity.md +62 -0
  139. package/reference/telemetry/metrics/index.md +150 -0
  140. package/reference/telemetry/metrics/instruments.md +183 -0
  141. package/reference/telemetry/metrics/labeled-instruments.md +74 -0
  142. package/reference/telemetry/metrics/meter-provider.md +76 -0
  143. package/reference/telemetry/metrics/meter.md +98 -0
  144. package/reference/telemetry/metrics/metric-data.md +57 -0
  145. package/reference/telemetry/otel/custom-exporter.md +216 -0
  146. package/reference/telemetry/otel/index.md +212 -0
  147. package/reference/telemetry/tracing/index.md +155 -0
  148. package/reference/telemetry/tracing/sampler.md +89 -0
  149. package/reference/telemetry/tracing/span-builder.md +57 -0
  150. package/reference/telemetry/tracing/span-context.md +39 -0
  151. package/reference/telemetry/tracing/span-data.md +32 -0
  152. package/reference/telemetry/tracing/span-kind.md +55 -0
  153. package/reference/telemetry/tracing/span-processor.md +53 -0
  154. package/reference/telemetry/tracing/span-status.md +47 -0
  155. package/reference/telemetry/tracing/span.md +117 -0
  156. package/reference/telemetry/tracing/tracer-provider.md +91 -0
  157. package/reference/telemetry/tracing/tracer.md +52 -0
  158. package/reference/typeid.md +0 -64
  159. package/sidebars.js +365 -185
  160. package/undocumented-report.md +528 -270
  161. package/reference/config.md +0 -158
  162. package/reference/streams/concurrent-operators.md +0 -106
  163. package/reference/streams/reader.md +0 -1284
  164. package/reference/streams/scala-2-compatibility.md +0 -55
  165. package/reference/streams/zero-boxing.md +0 -275
  166. package/reference/telemetry.md +0 -693
@@ -1,55 +0,0 @@
1
- ---
2
- id: scala-2-compatibility
3
- title: "Scala 2 Compatibility Design Note"
4
- sidebar_label: "Scala 2 Compatibility"
5
- ---
6
-
7
- This document explains the design of Scala 2.13 support for `zio.blocks.streams` and the constraints that shaped it.
8
-
9
- ## Motivation
10
-
11
- HTTP data types in `zio-blocks` depend on streams. `zio-http` 4 depends on those HTTP data types. Without Scala 2 stream support, `zio-http` cannot offer Scala 2 support. That dependency chain makes Scala 2.13 support for streams a hard requirement, not an optional nicety.
12
-
13
- ## Non-negotiable constraint: Scala 3 performance
14
-
15
- The streams implementation uses Scala 3 features on hot combinator paths, especially in `Stream` and `Sink` methods that participate in specialization, error-channel elimination, and zero-boxing-friendly code generation. The `inline` keyword on performance-sensitive helpers is not cosmetic; it directly affects what the JVM sees.
16
-
17
- A Scala 2 compatibility layer is only acceptable if it leaves the Scala 3 hot path structurally unchanged. Concretely, this rules out:
18
-
19
- - Moving key instance methods out of the Scala 3 class body into a shared trait
20
- - Removing or weakening `inline` definitions to satisfy Scala 2's lack of that feature
21
- - Introducing extra trait boundaries that alter the generated Scala 3 bytecode
22
-
23
- Adapting surface syntax from Scala 3 `using` to Scala 2 `implicit` is fine where it does not touch the hot path. The risk is not the spelling of contextual parameters; the risk is changing the runtime shape of `Stream` and `Sink` under Scala 3.
24
-
25
- ## Rejected approach: version-specific trait extraction
26
-
27
- An early draft extracted several instance methods into `StreamVersionSpecific` and `SinkVersionSpecific` traits under `scala-2/` and `scala-3/`, with the shared classes extending those traits. The methods moved or routed through these traits included:
28
-
29
- - `Stream.++`, `Stream.catchAll`, `Stream.catchDefect`, `Stream.concat`
30
- - `Stream.flatMap`, `Stream.mapError`, `Stream.orElse`, `Stream.&&`
31
- - `Sink.mapError`
32
-
33
- This shape localized the syntax differences neatly, but changed the structure of the Scala 3 hot path enough to produce measurable regressions. Benchmarks run with `streams-benchmark` on Scala 3.8.3 and JDK 25:
34
-
35
- | Benchmark | Baseline (`main`) | Trait-extraction draft | Change |
36
- |---|---:|---:|---|
37
- | `StreamPipelineBench.zb_flatMap` | 14924.328 ops/s | 1178.997 ops/s | ~12x regression |
38
- | `StreamPipelineBench.zb_concat` | 26003.818 ops/s | 22044.497 ops/s | regression |
39
- | `StreamPipelineBench.zb_filterMap` | 54812.709 ops/s | 50349.471 ops/s | regression |
40
-
41
- The `flatMap` result is the clearest signal. Dropping from roughly 14.9k ops/s to 1.18k ops/s is not an acceptable tradeoff for any compatibility layer. The approach was rejected.
42
-
43
- ## Chosen approach: full per-version split
44
-
45
- The implementation uses a full per-version source split. `Stream`, `Sink`, `Reader`, `Writer`, `Pipeline`, and `Interpreter` each have separate implementations under `scala-3/` and `scala-2/` source directories.
46
-
47
- Under `scala-3/`, the existing method bodies remain exactly as they were before Scala 2 support was added. `inline` helpers stay in place. No hot path is touched.
48
-
49
- Under `scala-2/`, equivalent semantics are provided using `final val` and `final def` where Scala 3 uses `inline val` and `inline def`. The Scala 2 surface is behaviorally equivalent; the Scala 2 compiler cannot honour `inline` in the same way, but the final modifier prevents virtual dispatch and allows the JIT similar opportunities.
50
-
51
- ## Maintenance notes
52
-
53
- Any change to the behavior or public API of `Stream`, `Sink`, `Reader`, `Writer`, `Pipeline`, or `Interpreter` must be applied to both the `scala-2/` and `scala-3/` source trees. The split is intentional and permanent; it is not scaffolding to be collapsed later.
54
-
55
- When making changes that touch hot combinators, re-run `streams-benchmark` and verify that `zb_flatMap`, `zb_concat`, and `zb_filterMap` do not regress relative to the `main` baseline.
@@ -1,275 +0,0 @@
1
- ---
2
- id: zero-boxing
3
- title: "Zero-Boxing Optimization"
4
- sidebar_label: "Zero-Boxing"
5
- ---
6
-
7
- Working with streams of primitives (integers, longs, doubles, booleans) presents a performance challenge in languages with generic types: **boxing**. Without special care, primitive values get wrapped in objects, causing memory waste and slower code. ZIO Blocks Streams eliminates this overhead entirely through a novel runtime type-dispatch system.
8
-
9
- ## The Boxing Problem
10
-
11
- In Scala, primitive types (`Int`, `Long`, `Double`, `Boolean`) are fundamentally different from their object counterparts (`Integer`, `Long`, `Double`, `Boolean`). When a generic class like `Stream[E, A]` works with primitives, the compiler must box them into objects to satisfy the generic contract:
12
-
13
- ```scala
14
- // Without optimization, this boxes each Int into an Integer object
15
- val stream: Stream[Nothing, Int] = Stream(1, 2, 3, 4, 5)
16
- val doubled = stream.map(_ * 2) // Each Int is boxed → Integer → boxed result
17
- val result = doubled.runCollect
18
- // Result: Each element was boxed, unboxed, boxed again — wasteful!
19
- ```
20
-
21
- **Performance cost:**
22
- - Extra heap allocations (memory pressure, more GC)
23
- - Cache misses (objects spread across memory)
24
- - Slower CPU operations (dereferencing objects instead of primitive registers)
25
-
26
- For high-throughput data processing, this overhead is unacceptable.
27
-
28
- ## ZIO Blocks Streams' Solution: JvmType Dispatch
29
-
30
- Instead of using Scala's `@specialized` annotation (which generates separate classes for each primitive type, bloating binaries), ZIO Blocks Streams uses **compile-time type detection + runtime dispatch**. This gives you the speed of specialization without the binary bloat.
31
-
32
- ### How It Works
33
-
34
- **Step 1: Compile-Time Detection**
35
-
36
- When you create a stream of primitives, the compiler infers a `JvmType` implicit that identifies the element type:
37
-
38
- ```scala
39
- val intStream: Stream[Nothing, Int] = Stream(1, 2, 3)
40
- // Compiler infers: JvmType.Infer[Int]
41
- // This information travels through the entire pipeline
42
-
43
- val doubled = intStream.map(_ * 2)
44
- // JvmType.Int is available to map's implementation
45
- ```
46
-
47
- **Step 2: Runtime Type Dispatch**
48
-
49
- Each operation (map, filter, scan, etc.) checks the type at runtime and uses the appropriate fast path:
50
-
51
- ```scala
52
- // Inside Stream#map's implementation
53
- def map[B](f: A => B)(implicit jvmTypeA: JvmType.Infer[A]): Stream[E, B] = {
54
- val jt = jvmTypeA.jvmType
55
-
56
- if (jt eq JvmType.Int) {
57
- // Fast unboxed path: read raw Int, apply function, write raw Int
58
- val intValue = reader.readInt(Long.MinValue)
59
- val result = f(intValue.asInstanceOf[A])
60
- // result stays unboxed if B is also Int
61
- } else if (jt eq JvmType.Long) {
62
- // Fast unboxed path for Long
63
- val longValue = reader.readLong(Long.MinValue)
64
- val result = f(longValue.asInstanceOf[A])
65
- } else {
66
- // Generic path: works for any type, uses boxing for primitives
67
- val value = reader.read(EndOfStream)
68
- val result = f(value)
69
- }
70
- }
71
- ```
72
-
73
- **Step 3: Unboxed Accessors**
74
-
75
- Instead of a single `read()` method that returns boxed `Any` (where boxed means wrapping primitives in object wrappers like `Integer`, `Long`, `Double`), primitives use specialized accessors that operate directly on primitive values:
76
-
77
- ```scala
78
- trait Reader[A] {
79
- // Generic: wraps primitives in objects (Integer, Long, etc.)
80
- def read(onEnd: A): A
81
-
82
- // Specialized: primitives stay unboxed
83
- def readInt(onEnd: Long): Int
84
- def readLong(onEnd: Long): Long
85
- def readDouble(onEnd: Long): Double
86
- def readBoolean(onEnd: Long): Boolean
87
- }
88
- ```
89
-
90
- The right method is called at runtime based on the detected type, so primitives bypass boxing entirely.
91
-
92
- ## Practical Benefits
93
-
94
- To understand the real-world impact, consider how boxing accumulates through a pipeline. Compare a hypothetical boxed implementation with ZIO Streams' zero-boxing approach.
95
-
96
- ### Before (Hypothetical Boxed Streams)
97
-
98
- Without optimization, each operation in a pipeline adds boxing overhead:
99
-
100
- ```scala
101
- val nums = Stream(1, 2, 3, 4, 5)
102
- val result = nums
103
- .map(_ * 2) // boxes each Int → Integer, applies *, unboxes result
104
- .filter(_ > 5) // boxes again, compares, unboxes
105
- .map(_ + 1) // boxes, adds, unboxes
106
- .runCollect
107
- // 5 elements × 3 operations × boxing overhead = significant waste
108
- ```
109
-
110
- **Memory profile:** Each element is boxed/unboxed multiple times, creating temporary objects.
111
-
112
- ### With ZIO Streams (Zero-Boxing)
113
-
114
- With ZIO Streams' zero-boxing optimization, the same pipeline avoids all boxing overhead:
115
-
116
- ```scala
117
- val nums = Stream(1, 2, 3, 4, 5)
118
- val result = nums
119
- .map(_ * 2) // operates on raw Int in CPU registers
120
- .filter(_ > 5) // compares raw Int directly
121
- .map(_ + 1) // raw Int arithmetic
122
- .runCollect
123
- // Zero boxing: primitives stay in registers and cache
124
- ```
125
-
126
- **Memory profile:** Same as non-generic code — primitives never leave the stack/registers.
127
-
128
- ## When Zero-Boxing Applies
129
-
130
- Zero-boxing is **automatic and transparent**. You get it for free when working with primitives:
131
-
132
- ```scala
133
- import zio.blocks.streams.*
134
-
135
- // ✓ Zero-boxing: Int, Long, Double, Boolean
136
- val ints = Stream(1, 2, 3).map(_ * 2)
137
- val longs = Stream(1L, 2L, 3L).filter(_ > 0L)
138
- val doubles = Stream(1.5, 2.5, 3.5).map(_ + 1.0)
139
- val bools = Stream(true, false, true).filter(identity)
140
-
141
- // ✓ Zero-boxing: case classes with primitives
142
- case class Point(x: Int, y: Int)
143
- val points = Stream(Point(1, 2), Point(3, 4))
144
- .map(p => Point(p.x * 2, p.y * 2))
145
-
146
- // ✓ Zero-boxing: tuples of primitives
147
- val pairs = Stream((1, 2), (3, 4))
148
- .map { case (x, y) => (x + 1, y + 1) }
149
-
150
- // Works, but may box for non-primitive types
151
- val strings = Stream("a", "b", "c").map(_.toUpperCase)
152
- ```
153
-
154
- You don't need to do anything special — the compiler and runtime handle it automatically.
155
-
156
- ## Comparison: @specialized vs JvmType Dispatch
157
-
158
- ZIO Blocks Streams' approach differs fundamentally from Scala's traditional `@specialized` annotation. Here's how they compare:
159
-
160
- **Traditional Scala `@specialized` annotation** generates separate specialized classes at compile time:
161
-
162
- ```scala
163
- @specialized(Int, Long, Double)
164
- class Stream[+E, +A] { ... }
165
- // Generates separate classes:
166
- // - Stream$mcI$sp (specialized for Int)
167
- // - Stream$mcJ$sp (specialized for Long)
168
- // - Stream$mcD$sp (specialized for Double)
169
- // - Stream (generic fallback)
170
- // Result: Binary size 4-5x larger
171
- ```
172
-
173
- **ZIO Blocks `JvmType` dispatch** uses runtime type checking in a single class:
174
-
175
- ```scala
176
- abstract class Stream[+E, +A] {
177
- def map[B](f: A => B)(implicit jvmType: JvmType.Infer[A]): Stream[E, B] = {
178
- if (jvmType.jvmType eq JvmType.Int) { /* fast path */ }
179
- else { /* generic path */ }
180
- }
181
- }
182
- // Single class, runtime dispatch
183
- // Result: Binary size normal, zero boxing at runtime
184
- ```
185
-
186
- | Metric | `@specialized` | JvmType |
187
- |--------|---|---|
188
- | **Binary size** | 4-5x larger | Normal |
189
- | **Bytecode complexity** | High | Moderate |
190
- | **Runtime dispatch** | None (compile-time) | Type check once per operation |
191
- | **Flexibility** | Fixed at compile time | Adaptive at runtime |
192
- | **Primitive support** | Configurable | Int, Long, Double, Boolean |
193
- | **Generality** | Good for all generics | Specialized for Stream/Sink |
194
-
195
- ## Implementation Architecture
196
-
197
- Zero-boxing works across ZIO Blocks Streams' three core abstractions:
198
-
199
- ### Stream[E, A]
200
-
201
- Detects element type via `JvmType.Infer[A]` and dispatches `Reader` accesses:
202
-
203
- ```scala
204
- import zio.blocks.streams.*
205
-
206
- val stream: Stream[Nothing, Int] = Stream(1, 2, 3)
207
- // JvmType.Int is inferred and available to all operations
208
- ```
209
-
210
- ### Sink[E, A, Z]
211
-
212
- Accepts elements via unboxed `write` methods matched to the detected type:
213
-
214
- ```scala
215
- import zio.blocks.streams.*
216
- import zio.blocks.chunk.Chunk
217
-
218
- val nums = Stream(1, 2, 3)
219
- val sum = nums.runFold(0)(_ + _)
220
- // Sink receives unboxed Int values
221
- ```
222
-
223
- ### Pipeline[A, B]
224
-
225
- Transforms elements without boxing when both A and B are primitives:
226
-
227
- ```scala
228
- import zio.blocks.streams.*
229
-
230
- val pipe = Pipeline.map[Int, Int](_ * 2)
231
- // Entire pipeline operates on raw Int
232
- ```
233
-
234
- ## Performance Impact
235
-
236
- For typical streaming workloads, zero-boxing provides **2-5x throughput improvement** over boxed approaches:
237
-
238
- - **CPU-bound operations** (map, filter, scan): 3-5x faster
239
- - **Memory-bound operations** (collect, fold): 2-3x faster
240
- - **I/O operations** (reading, writing): Minimal impact (I/O latency dominates)
241
-
242
- The benefit scales with pipeline depth and data volume. Shallow pipelines see modest gains; deep pipelines (>10 operations) over large datasets see dramatic improvements.
243
-
244
- ## When Polymorphism Is Necessary
245
-
246
- If you need polymorphic behavior (e.g., different handling for different types), use `JvmType` directly:
247
-
248
- ```scala
249
- import zio.blocks.streams.*
250
- import zio.blocks.streams.JvmType
251
-
252
- def processStream[A](stream: Stream[Nothing, A])(implicit jt: JvmType.Infer[A]): Unit = {
253
- jt.jvmType match {
254
- case JvmType.Int =>
255
- println("Processing integers")
256
- case JvmType.Long =>
257
- println("Processing longs")
258
- case _ =>
259
- println("Processing generic type")
260
- }
261
- }
262
- ```
263
-
264
- This gives you runtime type information while maintaining full zero-boxing performance.
265
-
266
- ## Summary
267
-
268
- ZIO Blocks Streams achieves **zero-boxing for primitives** through:
269
-
270
- 1. **Compile-time type detection** via `JvmType.Infer[A]` implicits
271
- 2. **Runtime dispatch** that selects specialized fast paths
272
- 3. **Unboxed accessors** that operate on raw primitives
273
- 4. **Transparent optimization** — you write high-level code, the system handles the details
274
-
275
- The result is **performance parity with hand-written imperative code** while maintaining the expressiveness and safety of functional streams. No binary bloat, no manual specialization annotations, no boxing overhead.