@smoothbricks/lmao 0.1.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.
- package/README.md +269 -0
- package/dist/allocator.wasm +0 -0
- package/dist/bun/preload.d.ts +11 -0
- package/dist/bun/preload.d.ts.map +1 -0
- package/dist/bun/preload.js +10 -0
- package/dist/bun/trace-preload.d.ts +8 -0
- package/dist/bun/trace-preload.d.ts.map +1 -0
- package/dist/bun/trace-preload.js +12 -0
- package/dist/es.d.ts +8 -0
- package/dist/es.d.ts.map +1 -0
- package/dist/es.js +9 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/lib/JsBufferStrategy.d.ts +49 -0
- package/dist/lib/JsBufferStrategy.d.ts.map +1 -0
- package/dist/lib/JsBufferStrategy.js +60 -0
- package/dist/lib/archive/chunkCompaction.d.ts +15 -0
- package/dist/lib/archive/chunkCompaction.d.ts.map +1 -0
- package/dist/lib/archive/chunkCompaction.js +24 -0
- package/dist/lib/archive/chunkEnvelope.d.ts +21 -0
- package/dist/lib/archive/chunkEnvelope.d.ts.map +1 -0
- package/dist/lib/archive/chunkEnvelope.js +55 -0
- package/dist/lib/archive/chunkRouting.d.ts +10 -0
- package/dist/lib/archive/chunkRouting.d.ts.map +1 -0
- package/dist/lib/archive/chunkRouting.js +47 -0
- package/dist/lib/archive/chunkStats.d.ts +12 -0
- package/dist/lib/archive/chunkStats.d.ts.map +1 -0
- package/dist/lib/archive/chunkStats.js +10 -0
- package/dist/lib/archive/index.d.ts +5 -0
- package/dist/lib/archive/index.d.ts.map +1 -0
- package/dist/lib/archive/index.js +4 -0
- package/dist/lib/arrow/capacityStats.d.ts +9 -0
- package/dist/lib/arrow/capacityStats.d.ts.map +1 -0
- package/dist/lib/arrow/capacityStats.js +231 -0
- package/dist/lib/arrow/dictionaries.d.ts +27 -0
- package/dist/lib/arrow/dictionaries.d.ts.map +1 -0
- package/dist/lib/arrow/dictionaries.js +135 -0
- package/dist/lib/arrow/flechette.d.ts +40 -0
- package/dist/lib/arrow/flechette.d.ts.map +1 -0
- package/dist/lib/arrow/flechette.js +67 -0
- package/dist/lib/arrow/utils.d.ts +38 -0
- package/dist/lib/arrow/utils.d.ts.map +1 -0
- package/dist/lib/arrow/utils.js +112 -0
- package/dist/lib/buffer/Nanoseconds.d.ts +109 -0
- package/dist/lib/buffer/Nanoseconds.d.ts.map +1 -0
- package/dist/lib/buffer/Nanoseconds.js +86 -0
- package/dist/lib/bufferStrategy.d.ts +95 -0
- package/dist/lib/bufferStrategy.d.ts.map +1 -0
- package/dist/lib/bufferStrategy.js +1 -0
- package/dist/lib/capacityTuning.d.ts +50 -0
- package/dist/lib/capacityTuning.d.ts.map +1 -0
- package/dist/lib/capacityTuning.js +65 -0
- package/dist/lib/codegen/evaluatorGenerator.d.ts +35 -0
- package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -0
- package/dist/lib/codegen/evaluatorGenerator.js +199 -0
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +139 -0
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -0
- package/dist/lib/codegen/fixedPositionWriterGenerator.js +289 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts +115 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -0
- package/dist/lib/codegen/spanLoggerGenerator.js +575 -0
- package/dist/lib/convertToArrow.d.ts +40 -0
- package/dist/lib/convertToArrow.d.ts.map +1 -0
- package/dist/lib/convertToArrow.js +1467 -0
- package/dist/lib/defineOpContext.d.ts +96 -0
- package/dist/lib/defineOpContext.d.ts.map +1 -0
- package/dist/lib/defineOpContext.js +227 -0
- package/dist/lib/errors/Blocked.d.ts +113 -0
- package/dist/lib/errors/Blocked.d.ts.map +1 -0
- package/dist/lib/errors/Blocked.js +68 -0
- package/dist/lib/errors/CodeError.d.ts +101 -0
- package/dist/lib/errors/CodeError.d.ts.map +1 -0
- package/dist/lib/errors/CodeError.js +42 -0
- package/dist/lib/errors/RetriesExhausted.d.ts +67 -0
- package/dist/lib/errors/RetriesExhausted.d.ts.map +1 -0
- package/dist/lib/errors/RetriesExhausted.js +31 -0
- package/dist/lib/errors/Transient.d.ts +115 -0
- package/dist/lib/errors/Transient.d.ts.map +1 -0
- package/dist/lib/errors/Transient.js +54 -0
- package/dist/lib/errors/index.d.ts +14 -0
- package/dist/lib/errors/index.d.ts.map +1 -0
- package/dist/lib/errors/index.js +16 -0
- package/dist/lib/errors/retry-policy.d.ts +60 -0
- package/dist/lib/errors/retry-policy.d.ts.map +1 -0
- package/dist/lib/errors/retry-policy.js +54 -0
- package/dist/lib/flushScheduler.d.ts +162 -0
- package/dist/lib/flushScheduler.d.ts.map +1 -0
- package/dist/lib/flushScheduler.js +388 -0
- package/dist/lib/library.d.ts +149 -0
- package/dist/lib/library.d.ts.map +1 -0
- package/dist/lib/library.js +588 -0
- package/dist/lib/logApi.d.ts +61 -0
- package/dist/lib/logApi.d.ts.map +1 -0
- package/dist/lib/logApi.js +12 -0
- package/dist/lib/logBinding.d.ts +63 -0
- package/dist/lib/logBinding.d.ts.map +1 -0
- package/dist/lib/logBinding.js +1 -0
- package/dist/lib/op.d.ts +105 -0
- package/dist/lib/op.d.ts.map +1 -0
- package/dist/lib/op.js +59 -0
- package/dist/lib/opContext/contextTypes.d.ts +88 -0
- package/dist/lib/opContext/contextTypes.d.ts.map +1 -0
- package/dist/lib/opContext/contextTypes.js +34 -0
- package/dist/lib/opContext/createOpGroup.d.ts +57 -0
- package/dist/lib/opContext/createOpGroup.d.ts.map +1 -0
- package/dist/lib/opContext/createOpGroup.js +341 -0
- package/dist/lib/opContext/defineOp.d.ts +83 -0
- package/dist/lib/opContext/defineOp.d.ts.map +1 -0
- package/dist/lib/opContext/defineOp.js +197 -0
- package/dist/lib/opContext/featureFlagTypes.d.ts +58 -0
- package/dist/lib/opContext/featureFlagTypes.d.ts.map +1 -0
- package/dist/lib/opContext/featureFlagTypes.js +1 -0
- package/dist/lib/opContext/index.d.ts +13 -0
- package/dist/lib/opContext/index.d.ts.map +1 -0
- package/dist/lib/opContext/index.js +15 -0
- package/dist/lib/opContext/opGroupTypes.d.ts +250 -0
- package/dist/lib/opContext/opGroupTypes.d.ts.map +1 -0
- package/dist/lib/opContext/opGroupTypes.js +31 -0
- package/dist/lib/opContext/opTypes.d.ts +48 -0
- package/dist/lib/opContext/opTypes.d.ts.map +1 -0
- package/dist/lib/opContext/opTypes.js +7 -0
- package/dist/lib/opContext/spanContextTypes.d.ts +347 -0
- package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -0
- package/dist/lib/opContext/spanContextTypes.js +1 -0
- package/dist/lib/opContext/types.d.ts +297 -0
- package/dist/lib/opContext/types.d.ts.map +1 -0
- package/dist/lib/opContext/types.js +16 -0
- package/dist/lib/result.d.ts +308 -0
- package/dist/lib/result.d.ts.map +1 -0
- package/dist/lib/result.js +359 -0
- package/dist/lib/schema/LogSchema.d.ts +62 -0
- package/dist/lib/schema/LogSchema.d.ts.map +1 -0
- package/dist/lib/schema/LogSchema.js +134 -0
- package/dist/lib/schema/builder.d.ts +12 -0
- package/dist/lib/schema/builder.d.ts.map +1 -0
- package/dist/lib/schema/builder.js +169 -0
- package/dist/lib/schema/defineFeatureFlags.d.ts +60 -0
- package/dist/lib/schema/defineFeatureFlags.d.ts.map +1 -0
- package/dist/lib/schema/defineFeatureFlags.js +29 -0
- package/dist/lib/schema/defineLogSchema.d.ts +87 -0
- package/dist/lib/schema/defineLogSchema.d.ts.map +1 -0
- package/dist/lib/schema/defineLogSchema.js +171 -0
- package/dist/lib/schema/evaluator.d.ts +267 -0
- package/dist/lib/schema/evaluator.d.ts.map +1 -0
- package/dist/lib/schema/evaluator.js +169 -0
- package/dist/lib/schema/extend.d.ts +14 -0
- package/dist/lib/schema/extend.d.ts.map +1 -0
- package/dist/lib/schema/extend.js +51 -0
- package/dist/lib/schema/systemSchema.d.ts +112 -0
- package/dist/lib/schema/systemSchema.d.ts.map +1 -0
- package/dist/lib/schema/systemSchema.js +260 -0
- package/dist/lib/schema/typeGuards.d.ts +52 -0
- package/dist/lib/schema/typeGuards.d.ts.map +1 -0
- package/dist/lib/schema/typeGuards.js +127 -0
- package/dist/lib/schema/types.d.ts +156 -0
- package/dist/lib/schema/types.d.ts.map +1 -0
- package/dist/lib/schema/types.js +4 -0
- package/dist/lib/spanBuffer.d.ts +133 -0
- package/dist/lib/spanBuffer.d.ts.map +1 -0
- package/dist/lib/spanBuffer.js +442 -0
- package/dist/lib/spanBufferHelpers.d.ts +53 -0
- package/dist/lib/spanBufferHelpers.d.ts.map +1 -0
- package/dist/lib/spanBufferHelpers.js +65 -0
- package/dist/lib/spanBufferStats.d.ts +38 -0
- package/dist/lib/spanBufferStats.d.ts.map +1 -0
- package/dist/lib/spanBufferStats.js +1 -0
- package/dist/lib/spanContext.d.ts +141 -0
- package/dist/lib/spanContext.d.ts.map +1 -0
- package/dist/lib/spanContext.js +763 -0
- package/dist/lib/sqlite/index.d.ts +14 -0
- package/dist/lib/sqlite/index.d.ts.map +1 -0
- package/dist/lib/sqlite/index.js +12 -0
- package/dist/lib/sqlite/sqlite-async-writer.d.ts +24 -0
- package/dist/lib/sqlite/sqlite-async-writer.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-async-writer.js +65 -0
- package/dist/lib/sqlite/sqlite-common.d.ts +37 -0
- package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-common.js +207 -0
- package/dist/lib/sqlite/sqlite-d1.d.ts +25 -0
- package/dist/lib/sqlite/sqlite-d1.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-d1.js +67 -0
- package/dist/lib/sqlite/sqlite-db.d.ts +29 -0
- package/dist/lib/sqlite/sqlite-db.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-db.js +1 -0
- package/dist/lib/sqlite/sqlite-node.d.ts +16 -0
- package/dist/lib/sqlite/sqlite-node.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-node.js +68 -0
- package/dist/lib/sqlite/sqlite-writer.d.ts +39 -0
- package/dist/lib/sqlite/sqlite-writer.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-writer.js +78 -0
- package/dist/lib/testing/bun-harness.d.ts +150 -0
- package/dist/lib/testing/bun-harness.d.ts.map +1 -0
- package/dist/lib/testing/bun-harness.js +729 -0
- package/dist/lib/testing/extractFacts.d.ts +73 -0
- package/dist/lib/testing/extractFacts.d.ts.map +1 -0
- package/dist/lib/testing/extractFacts.js +237 -0
- package/dist/lib/testing/facts.d.ts +235 -0
- package/dist/lib/testing/facts.d.ts.map +1 -0
- package/dist/lib/testing/facts.js +209 -0
- package/dist/lib/testing/index.d.ts +58 -0
- package/dist/lib/testing/index.d.ts.map +1 -0
- package/dist/lib/testing/index.js +74 -0
- package/dist/lib/testing/queryable-span.d.ts +39 -0
- package/dist/lib/testing/queryable-span.d.ts.map +1 -0
- package/dist/lib/testing/queryable-span.js +58 -0
- package/dist/lib/testing/span-query.d.ts +21 -0
- package/dist/lib/testing/span-query.d.ts.map +1 -0
- package/dist/lib/testing/span-query.js +47 -0
- package/dist/lib/testing/stdio-replay.d.ts +4 -0
- package/dist/lib/testing/stdio-replay.d.ts.map +1 -0
- package/dist/lib/testing/stdio-replay.js +42 -0
- package/dist/lib/testing/trace-query.d.ts +59 -0
- package/dist/lib/testing/trace-query.d.ts.map +1 -0
- package/dist/lib/testing/trace-query.js +462 -0
- package/dist/lib/testing/vitest-harness.d.ts +135 -0
- package/dist/lib/testing/vitest-harness.d.ts.map +1 -0
- package/dist/lib/testing/vitest-harness.js +486 -0
- package/dist/lib/threadId.d.ts +58 -0
- package/dist/lib/threadId.d.ts.map +1 -0
- package/dist/lib/threadId.js +123 -0
- package/dist/lib/traceContext.d.ts +116 -0
- package/dist/lib/traceContext.d.ts.map +1 -0
- package/dist/lib/traceContext.js +37 -0
- package/dist/lib/traceId.d.ts +78 -0
- package/dist/lib/traceId.d.ts.map +1 -0
- package/dist/lib/traceId.js +87 -0
- package/dist/lib/traceRoot.d.ts +133 -0
- package/dist/lib/traceRoot.d.ts.map +1 -0
- package/dist/lib/traceRoot.es.d.ts +75 -0
- package/dist/lib/traceRoot.es.d.ts.map +1 -0
- package/dist/lib/traceRoot.es.js +129 -0
- package/dist/lib/traceRoot.js +19 -0
- package/dist/lib/traceRoot.node.d.ts +77 -0
- package/dist/lib/traceRoot.node.d.ts.map +1 -0
- package/dist/lib/traceRoot.node.js +133 -0
- package/dist/lib/traceRoot.universal.d.ts +3 -0
- package/dist/lib/traceRoot.universal.d.ts.map +1 -0
- package/dist/lib/traceRoot.universal.js +17 -0
- package/dist/lib/tracer.d.ts +296 -0
- package/dist/lib/tracer.d.ts.map +1 -0
- package/dist/lib/tracer.js +346 -0
- package/dist/lib/tracers/ArrayQueueTracer.d.ts +56 -0
- package/dist/lib/tracers/ArrayQueueTracer.d.ts.map +1 -0
- package/dist/lib/tracers/ArrayQueueTracer.js +67 -0
- package/dist/lib/tracers/CompositeTracer.d.ts +24 -0
- package/dist/lib/tracers/CompositeTracer.d.ts.map +1 -0
- package/dist/lib/tracers/CompositeTracer.js +57 -0
- package/dist/lib/tracers/NoOpTracer.d.ts +58 -0
- package/dist/lib/tracers/NoOpTracer.d.ts.map +1 -0
- package/dist/lib/tracers/NoOpTracer.js +41 -0
- package/dist/lib/tracers/SQLiteTracer.d.ts +42 -0
- package/dist/lib/tracers/SQLiteTracer.d.ts.map +1 -0
- package/dist/lib/tracers/SQLiteTracer.js +84 -0
- package/dist/lib/tracers/StdioTracer.d.ts +83 -0
- package/dist/lib/tracers/StdioTracer.d.ts.map +1 -0
- package/dist/lib/tracers/StdioTracer.js +270 -0
- package/dist/lib/tracers/TestTracer.d.ts +95 -0
- package/dist/lib/tracers/TestTracer.d.ts.map +1 -0
- package/dist/lib/tracers/TestTracer.js +87 -0
- package/dist/lib/tracers/index.d.ts +12 -0
- package/dist/lib/tracers/index.d.ts.map +1 -0
- package/dist/lib/tracers/index.js +11 -0
- package/dist/lib/types.d.ts +366 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/utf8Cache.d.ts +111 -0
- package/dist/lib/utf8Cache.d.ts.map +1 -0
- package/dist/lib/utf8Cache.js +177 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts +88 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -0
- package/dist/lib/wasm/WasmBufferStrategy.js +138 -0
- package/dist/lib/wasm/wasmAllocator.d.ts +109 -0
- package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -0
- package/dist/lib/wasm/wasmAllocator.js +227 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts +123 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -0
- package/dist/lib/wasm/wasmSpanBuffer.js +772 -0
- package/dist/lib/wasm/wasmTraceRoot.d.ts +167 -0
- package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -0
- package/dist/lib/wasm/wasmTraceRoot.js +264 -0
- package/dist/node.d.ts +7 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +8 -0
- package/dist/testing.d.ts +18 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +17 -0
- package/package.json +193 -0
- package/src/bun/preload.ts +11 -0
- package/src/bun/trace-preload.ts +14 -0
- package/src/es.ts +11 -0
- package/src/index.ts +194 -0
- package/src/lib/JsBufferStrategy.ts +102 -0
- package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +485 -0
- package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +390 -0
- package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +647 -0
- package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +292 -0
- package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +354 -0
- package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +127 -0
- package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +392 -0
- package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +389 -0
- package/src/lib/__tests__/arrow-conversion-algorithms.test.ts +54 -0
- package/src/lib/__tests__/arrow-test-helpers.ts +71 -0
- package/src/lib/__tests__/binary-e2e.test.ts +203 -0
- package/src/lib/__tests__/buffer-overflow-op-api.test.ts +608 -0
- package/src/lib/__tests__/buffer-overflow.test.ts +612 -0
- package/src/lib/__tests__/capacity-tuning.test.ts +544 -0
- package/src/lib/__tests__/effective-schema.test.ts +439 -0
- package/src/lib/__tests__/flechette.test.ts +42 -0
- package/src/lib/__tests__/flushScheduler.test.ts +537 -0
- package/src/lib/__tests__/integration.test.ts +600 -0
- package/src/lib/__tests__/library.test.ts +934 -0
- package/src/lib/__tests__/nested-library-tasks.test.ts +849 -0
- package/src/lib/__tests__/op-context-binding.test.ts +135 -0
- package/src/lib/__tests__/op-metadata.test.ts +198 -0
- package/src/lib/__tests__/op-type-safety.test.ts +71 -0
- package/src/lib/__tests__/package-exports.test.ts +57 -0
- package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +319 -0
- package/src/lib/__tests__/remapped-buffer-view.test.ts +635 -0
- package/src/lib/__tests__/scope-attributes.test.ts +348 -0
- package/src/lib/__tests__/span-lifecycle.test.ts +680 -0
- package/src/lib/__tests__/sync-async-trace.test.ts +435 -0
- package/src/lib/__tests__/test-helpers.ts +318 -0
- package/src/lib/__tests__/timestamp.test.ts +259 -0
- package/src/lib/__tests__/trace-archive-primitives.test.ts +98 -0
- package/src/lib/__tests__/traceContext-type-enforcement.test.ts +271 -0
- package/src/lib/__tests__/tracer.test.ts +211 -0
- package/src/lib/__tests__/type-narrowing.test.ts +137 -0
- package/src/lib/archive/chunkCompaction.ts +44 -0
- package/src/lib/archive/chunkEnvelope.ts +79 -0
- package/src/lib/archive/chunkRouting.ts +70 -0
- package/src/lib/archive/chunkStats.ts +25 -0
- package/src/lib/archive/index.ts +4 -0
- package/src/lib/arrow/capacityStats.ts +340 -0
- package/src/lib/arrow/dictionaries.ts +159 -0
- package/src/lib/arrow/flechette.ts +114 -0
- package/src/lib/arrow/utils.ts +126 -0
- package/src/lib/buffer/Nanoseconds.ts +131 -0
- package/src/lib/bufferStrategy.ts +106 -0
- package/src/lib/capacityTuning.ts +102 -0
- package/src/lib/codegen/__tests__/__snapshots__/evaluatorGenerator.test.ts.snap +160 -0
- package/src/lib/codegen/__tests__/__snapshots__/scopeGenerator.test.ts.snap +196 -0
- package/src/lib/codegen/__tests__/__snapshots__/spanLoggerGenerator.test.ts.snap +1965 -0
- package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +516 -0
- package/src/lib/codegen/__tests__/nullBitmap.test.ts +207 -0
- package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +237 -0
- package/src/lib/codegen/evaluatorGenerator.ts +309 -0
- package/src/lib/codegen/fixedPositionWriterGenerator.ts +444 -0
- package/src/lib/codegen/spanLoggerGenerator.ts +715 -0
- package/src/lib/convertToArrow.ts +1805 -0
- package/src/lib/defineOpContext.ts +398 -0
- package/src/lib/errors/Blocked.ts +165 -0
- package/src/lib/errors/CodeError.ts +132 -0
- package/src/lib/errors/RetriesExhausted.ts +78 -0
- package/src/lib/errors/Transient.ts +168 -0
- package/src/lib/errors/__tests__/Blocked-config.test.ts +152 -0
- package/src/lib/errors/__tests__/Transient.test.ts +129 -0
- package/src/lib/errors/__tests__/retry-policy.test.ts +85 -0
- package/src/lib/errors/index.ts +24 -0
- package/src/lib/errors/retry-policy.ts +87 -0
- package/src/lib/flushScheduler.ts +509 -0
- package/src/lib/library.ts +682 -0
- package/src/lib/logApi.ts +70 -0
- package/src/lib/logBinding.ts +67 -0
- package/src/lib/op.ts +103 -0
- package/src/lib/opContext/__tests__/retry.test.ts +764 -0
- package/src/lib/opContext/contextTypes.ts +130 -0
- package/src/lib/opContext/createOpGroup.ts +456 -0
- package/src/lib/opContext/defineOp.ts +281 -0
- package/src/lib/opContext/featureFlagTypes.ts +54 -0
- package/src/lib/opContext/index.ts +16 -0
- package/src/lib/opContext/opGroupTypes.ts +342 -0
- package/src/lib/opContext/opTypes.ts +80 -0
- package/src/lib/opContext/spanContextTypes.ts +398 -0
- package/src/lib/opContext/types.ts +403 -0
- package/src/lib/result.ts +550 -0
- package/src/lib/schema/LogSchema.ts +153 -0
- package/src/lib/schema/__tests__/defineLogSchema.test.ts +342 -0
- package/src/lib/schema/__tests__/featureFlags.test.ts +443 -0
- package/src/lib/schema/builder.ts +201 -0
- package/src/lib/schema/defineFeatureFlags.ts +91 -0
- package/src/lib/schema/defineLogSchema.ts +291 -0
- package/src/lib/schema/evaluator.ts +404 -0
- package/src/lib/schema/extend.ts +69 -0
- package/src/lib/schema/systemSchema.ts +339 -0
- package/src/lib/schema/typeGuards.ts +163 -0
- package/src/lib/schema/types.ts +265 -0
- package/src/lib/spanBuffer.ts +571 -0
- package/src/lib/spanBufferHelpers.ts +73 -0
- package/src/lib/spanBufferStats.ts +40 -0
- package/src/lib/spanContext.ts +1566 -0
- package/src/lib/sqlite/__tests__/sqlite-common.test.ts +89 -0
- package/src/lib/sqlite/index.ts +26 -0
- package/src/lib/sqlite/sqlite-async-writer.ts +101 -0
- package/src/lib/sqlite/sqlite-common.ts +309 -0
- package/src/lib/sqlite/sqlite-d1.ts +104 -0
- package/src/lib/sqlite/sqlite-db.ts +32 -0
- package/src/lib/sqlite/sqlite-node.ts +83 -0
- package/src/lib/sqlite/sqlite-writer.ts +128 -0
- package/src/lib/testing/TRACE-TESTING.md +100 -0
- package/src/lib/testing/__tests__/bun-harness.test.ts +108 -0
- package/src/lib/testing/__tests__/extractFacts.test.ts +279 -0
- package/src/lib/testing/__tests__/facts.test.ts +324 -0
- package/src/lib/testing/__tests__/vitest-harness.test.ts +32 -0
- package/src/lib/testing/bun-harness.ts +990 -0
- package/src/lib/testing/extractFacts.ts +362 -0
- package/src/lib/testing/facts.ts +470 -0
- package/src/lib/testing/index.ts +141 -0
- package/src/lib/testing/queryable-span.ts +108 -0
- package/src/lib/testing/span-query.ts +65 -0
- package/src/lib/testing/stdio-replay.ts +50 -0
- package/src/lib/testing/trace-query.ts +329 -0
- package/src/lib/testing/vitest-harness.ts +691 -0
- package/src/lib/threadId.ts +135 -0
- package/src/lib/traceContext.ts +182 -0
- package/src/lib/traceId.ts +142 -0
- package/src/lib/traceRoot.es.ts +157 -0
- package/src/lib/traceRoot.node.ts +170 -0
- package/src/lib/traceRoot.ts +154 -0
- package/src/lib/traceRoot.universal.ts +22 -0
- package/src/lib/tracer.ts +896 -0
- package/src/lib/tracers/ArrayQueueTracer.ts +76 -0
- package/src/lib/tracers/CompositeTracer.ts +76 -0
- package/src/lib/tracers/NoOpTracer.ts +73 -0
- package/src/lib/tracers/SQLiteTracer.ts +115 -0
- package/src/lib/tracers/StdioTracer.ts +380 -0
- package/src/lib/tracers/TestTracer.ts +146 -0
- package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +184 -0
- package/src/lib/tracers/__tests__/NoOpTracer.test.ts +204 -0
- package/src/lib/tracers/__tests__/StdioTracer.test.ts +313 -0
- package/src/lib/tracers/__tests__/TestTracer.test.ts +200 -0
- package/src/lib/tracers/index.ts +12 -0
- package/src/lib/types.ts +498 -0
- package/src/lib/utf8Cache.ts +201 -0
- package/src/lib/wasm/WasmBufferStrategy.ts +219 -0
- package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +256 -0
- package/src/lib/wasm/__tests__/wasm-integration.test.ts +476 -0
- package/src/lib/wasm/__tests__/wasmAllocator.test.ts +699 -0
- package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +449 -0
- package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +390 -0
- package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +444 -0
- package/src/lib/wasm/allocator.zig +945 -0
- package/src/lib/wasm/wasmAllocator.ts +469 -0
- package/src/lib/wasm/wasmSpanBuffer.ts +1014 -0
- package/src/lib/wasm/wasmTraceRoot.ts +315 -0
- package/src/node.ts +10 -0
- package/src/testing.ts +18 -0
|
@@ -0,0 +1,945 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Freelist Allocator for SpanBuffer Storage
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Implements spec 01q: WASM Memory Architecture for SpanBuffer Storage
|
|
6
|
+
//
|
|
7
|
+
// Memory Layout:
|
|
8
|
+
// ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
9
|
+
// │ Header (64 bytes, cache-aligned) │
|
|
10
|
+
// ├─────────────────────────────────────────────────────────────────────────────┤
|
|
11
|
+
// │ Allocated Blocks (spans + columns) │
|
|
12
|
+
// ├─────────────────────────────────────────────────────────────────────────────┤
|
|
13
|
+
// │ Free Space (bump allocation area) ↑ bump_ptr │
|
|
14
|
+
// └─────────────────────────────────────────────────────────────────────────────┘
|
|
15
|
+
//
|
|
16
|
+
// Size Classes:
|
|
17
|
+
// - Span System: capacity × 9 bytes (timestamp + entry_type)
|
|
18
|
+
// - Identity: 128 bytes (writeIndex + span_id + trace_id)
|
|
19
|
+
// - 1B Column: ceil(capacity/8) + capacity × 1 (nulls + uint8/bool values)
|
|
20
|
+
// - 4B Column: ceil(capacity/8) + capacity × 4 (nulls + uint32/float32 values)
|
|
21
|
+
// - 8B Column: ceil(capacity/8) + capacity × 8 (nulls + float64/bigint64 values)
|
|
22
|
+
//
|
|
23
|
+
// Freelist: Zero-overhead, uses block's memory for next pointer + cascading stats when free.
|
|
24
|
+
//
|
|
25
|
+
|
|
26
|
+
const std = @import("std");
|
|
27
|
+
|
|
28
|
+
// =============================================================================
|
|
29
|
+
// Packed Structs for Memory Layout
|
|
30
|
+
// =============================================================================
|
|
31
|
+
|
|
32
|
+
// =============================================================================
|
|
33
|
+
// Capacity Tiers for Buddy Allocation
|
|
34
|
+
// =============================================================================
|
|
35
|
+
// Tiers: 8, 16, 32, 64, 128, 256, 512 (7 tiers, index 0-6)
|
|
36
|
+
// Buddy relationship: tier[i] can split into 2× tier[i-1], merge into tier[i+1]
|
|
37
|
+
|
|
38
|
+
const MIN_CAPACITY: u32 = 8;
|
|
39
|
+
const MAX_CAPACITY: u32 = 512;
|
|
40
|
+
const NUM_TIERS: usize = 7; // log2(512/8) + 1 = 7
|
|
41
|
+
const NUM_SIZE_CLASSES: usize = 4;
|
|
42
|
+
const NUM_FREELISTS: usize = NUM_SIZE_CLASSES * NUM_TIERS; // 28
|
|
43
|
+
|
|
44
|
+
/// Convert capacity to tier index (0=8, 1=16, 2=32, 3=64, 4=128, 5=256, 6=512)
|
|
45
|
+
inline fn capacityToTier(capacity: u32) usize {
|
|
46
|
+
// capacity must be power of 2 between 8 and 512
|
|
47
|
+
return @ctz(capacity) - @ctz(MIN_CAPACITY);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// Convert tier index to capacity
|
|
51
|
+
inline fn tierToCapacity(tier: usize) u32 {
|
|
52
|
+
return MIN_CAPACITY << @intCast(tier);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// Header at offset 0 of WASM memory (192 bytes, 3 cache lines)
|
|
56
|
+
/// Uses extern struct for stable ABI layout
|
|
57
|
+
/// Hot fields in first cache line (64 bytes)
|
|
58
|
+
const Header = extern struct {
|
|
59
|
+
// === First cache line (hot) ===
|
|
60
|
+
bump_ptr: u32, // offset 0: Next free byte for bump allocation
|
|
61
|
+
span_id_counter: u32, // offset 4: Global span ID counter
|
|
62
|
+
alloc_count: u32, // offset 8: Total allocations
|
|
63
|
+
free_count: u32, // offset 12: Total frees
|
|
64
|
+
freelist_identity: u32, // offset 16: Identity freelist head
|
|
65
|
+
_pad0: u32, // offset 20: Align thread_id to 8 bytes
|
|
66
|
+
thread_id: u64, // offset 24: Process/worker thread ID
|
|
67
|
+
|
|
68
|
+
// Freelists start at offset 32 (inside first cache line)
|
|
69
|
+
// 4 size classes × 7 tiers = 28 freelists (112 bytes)
|
|
70
|
+
// Index: size_class * NUM_TIERS + tier
|
|
71
|
+
// Size classes: 0=span_system, 1=col_1b, 2=col_4b, 3=col_8b
|
|
72
|
+
freelists: [NUM_FREELISTS]u32, // offset 32-143
|
|
73
|
+
|
|
74
|
+
// === Cold fields ===
|
|
75
|
+
thread_id_set: u8, // offset 144: 1 if thread_id has been set
|
|
76
|
+
|
|
77
|
+
// Padding to 192 bytes (192 - 145 = 47 bytes)
|
|
78
|
+
_reserved: [47]u8,
|
|
79
|
+
|
|
80
|
+
comptime {
|
|
81
|
+
std.debug.assert(@sizeOf(Header) == 192);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/// Identity block (128 bytes fixed) - per-span metadata
|
|
86
|
+
/// Uses extern struct for stable ABI layout with array field
|
|
87
|
+
const Identity = extern struct {
|
|
88
|
+
write_index: u32, // Current write position (hot path, at offset 0)
|
|
89
|
+
span_id: u32, // Unique span ID (from global counter)
|
|
90
|
+
trace_id_len: u8, // Length of trace_id (0 for child buffers)
|
|
91
|
+
trace_id: [119]u8, // UTF-8 trace_id bytes (only for root buffers)
|
|
92
|
+
|
|
93
|
+
comptime {
|
|
94
|
+
std.debug.assert(@sizeOf(Identity) == 128);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/// TraceRoot timing data (16 bytes)
|
|
99
|
+
/// Uses extern struct for stable ABI layout
|
|
100
|
+
const TraceRoot = extern struct {
|
|
101
|
+
wall_clock_nanos: i64, // Wall clock start time in nanoseconds
|
|
102
|
+
monotonic_ms: f64, // Monotonic start time in milliseconds
|
|
103
|
+
|
|
104
|
+
comptime {
|
|
105
|
+
std.debug.assert(@sizeOf(TraceRoot) == 16);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/// Freelist block header - overlays the first 20 bytes of any freed block
|
|
110
|
+
/// Stores cascading statistics that aggregate as blocks are pushed/popped
|
|
111
|
+
/// Uses extern struct for stable ABI layout
|
|
112
|
+
const FreeBlock = extern struct {
|
|
113
|
+
next_ptr: u32, // Pointer to next free block (0 = end of list)
|
|
114
|
+
freelist_len: u32, // Number of blocks in freelist (cascading sum)
|
|
115
|
+
reuse_count: u32, // Times allocated from freelist (cascading sum)
|
|
116
|
+
split_count: u32, // Times this size class was split (cascading)
|
|
117
|
+
merge_count: u32, // Times blocks merged (cascading)
|
|
118
|
+
|
|
119
|
+
comptime {
|
|
120
|
+
std.debug.assert(@sizeOf(FreeBlock) == 20);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// =============================================================================
|
|
125
|
+
// Size Classes
|
|
126
|
+
// =============================================================================
|
|
127
|
+
|
|
128
|
+
const SizeClass = enum(u8) {
|
|
129
|
+
span_system = 0,
|
|
130
|
+
col_1b = 1,
|
|
131
|
+
col_4b = 2,
|
|
132
|
+
col_8b = 3,
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Identity is separate (fixed size, not capacity-dependent)
|
|
136
|
+
const IDENTITY_SIZE_CLASS: u8 = 4;
|
|
137
|
+
|
|
138
|
+
// =============================================================================
|
|
139
|
+
// Entry Type Constants (per specs/lmao/01h and systemSchema.ts)
|
|
140
|
+
// =============================================================================
|
|
141
|
+
|
|
142
|
+
const ENTRY_TYPE_SPAN_START: u8 = 1;
|
|
143
|
+
const ENTRY_TYPE_SPAN_OK: u8 = 2;
|
|
144
|
+
const ENTRY_TYPE_SPAN_ERR: u8 = 3;
|
|
145
|
+
const ENTRY_TYPE_SPAN_EXCEPTION: u8 = 4;
|
|
146
|
+
|
|
147
|
+
// No global capacity state - capacity is passed to each alloc/free call.
|
|
148
|
+
// This allows different OpContexts to have different capacities sharing the same WASM memory.
|
|
149
|
+
|
|
150
|
+
// =============================================================================
|
|
151
|
+
// Memory Access Helpers
|
|
152
|
+
// =============================================================================
|
|
153
|
+
|
|
154
|
+
/// Get typed pointer to WASM memory at offset.
|
|
155
|
+
/// Uses allowzero because WASM memory starts at address 0.
|
|
156
|
+
inline fn ptrAt(comptime T: type, offset: u32) *allowzero T {
|
|
157
|
+
return @ptrFromInt(offset);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/// Get byte slice pointer at offset
|
|
161
|
+
inline fn bytesAt(offset: u32) [*]allowzero u8 {
|
|
162
|
+
return @ptrFromInt(offset);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/// Get the global header at offset 0
|
|
166
|
+
inline fn header() *allowzero Header {
|
|
167
|
+
return ptrAt(Header, 0);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// =============================================================================
|
|
171
|
+
// Size Class Helpers
|
|
172
|
+
// =============================================================================
|
|
173
|
+
|
|
174
|
+
/// Get freelist index for a size class and capacity tier
|
|
175
|
+
inline fn freelistIndex(sc: SizeClass, tier: usize) usize {
|
|
176
|
+
return @intFromEnum(sc) * NUM_TIERS + tier;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/// Get freelist head for a size class at specific tier
|
|
180
|
+
inline fn freelistHeadAtTier(sc: SizeClass, tier: usize) u32 {
|
|
181
|
+
return header().freelists[freelistIndex(sc, tier)];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/// Set freelist head for a size class at specific tier
|
|
185
|
+
inline fn setFreelistHeadAtTier(sc: SizeClass, tier: usize, value: u32) void {
|
|
186
|
+
header().freelists[freelistIndex(sc, tier)] = value;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/// Get block size for a size class at a given capacity
|
|
190
|
+
inline fn blockSizeForCapacity(sc: SizeClass, capacity: u32) u32 {
|
|
191
|
+
const null_bitmap_size = (capacity + 7) >> 3;
|
|
192
|
+
return switch (sc) {
|
|
193
|
+
.span_system => capacity * 9,
|
|
194
|
+
.col_1b => null_bitmap_size + capacity,
|
|
195
|
+
.col_4b => null_bitmap_size + capacity * 4,
|
|
196
|
+
.col_8b => null_bitmap_size + capacity * 8,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// =============================================================================
|
|
201
|
+
// Allocator Core
|
|
202
|
+
// =============================================================================
|
|
203
|
+
|
|
204
|
+
/// Allocate a block from the given size class at specific tier.
|
|
205
|
+
fn allocAtTier(sc: SizeClass, tier: usize) u32 {
|
|
206
|
+
const h = header();
|
|
207
|
+
const head_offset = freelistHeadAtTier(sc, tier);
|
|
208
|
+
|
|
209
|
+
if (head_offset != 0) {
|
|
210
|
+
// Pop from freelist
|
|
211
|
+
const free_block = ptrAt(FreeBlock, head_offset);
|
|
212
|
+
const next = free_block.next_ptr;
|
|
213
|
+
setFreelistHeadAtTier(sc, tier, next);
|
|
214
|
+
|
|
215
|
+
// Cascade stats forward: copy from popped block to new head, then increment
|
|
216
|
+
// This ensures the new head has the aggregate stats from the entire chain
|
|
217
|
+
if (next != 0) {
|
|
218
|
+
const next_block = ptrAt(FreeBlock, next);
|
|
219
|
+
next_block.freelist_len = free_block.freelist_len - 1;
|
|
220
|
+
next_block.reuse_count = free_block.reuse_count + 1;
|
|
221
|
+
next_block.split_count = free_block.split_count;
|
|
222
|
+
next_block.merge_count = free_block.merge_count;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
h.alloc_count += 1;
|
|
226
|
+
return head_offset;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Freelist empty - try buddy split from larger tier
|
|
230
|
+
if (tier + 1 < NUM_TIERS) {
|
|
231
|
+
const parent_offset = allocAtTier(sc, tier + 1);
|
|
232
|
+
if (parent_offset != 0) {
|
|
233
|
+
// Split parent into two blocks of current tier size
|
|
234
|
+
const child_size = blockSizeForCapacity(sc, tierToCapacity(tier));
|
|
235
|
+
const second_child = parent_offset + child_size;
|
|
236
|
+
|
|
237
|
+
// Push second child to freelist (no merge attempt - it's a fresh split)
|
|
238
|
+
pushToFreelist(second_child, sc, tier, false);
|
|
239
|
+
|
|
240
|
+
// Update split count in the freelist head
|
|
241
|
+
const new_head = freelistHeadAtTier(sc, tier);
|
|
242
|
+
if (new_head != 0) {
|
|
243
|
+
ptrAt(FreeBlock, new_head).split_count += 1;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Return first child
|
|
247
|
+
return parent_offset;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// No buddy available - bump allocate
|
|
252
|
+
const size = blockSizeForCapacity(sc, tierToCapacity(tier));
|
|
253
|
+
const current_bump = h.bump_ptr;
|
|
254
|
+
|
|
255
|
+
// Align to 8 bytes
|
|
256
|
+
const aligned = (current_bump + 7) & ~@as(u32, 7);
|
|
257
|
+
const new_bump = aligned + size;
|
|
258
|
+
|
|
259
|
+
// Grow memory if needed
|
|
260
|
+
const current_size = @wasmMemorySize(0) * 65536; // pages * 64KB
|
|
261
|
+
if (new_bump > current_size) {
|
|
262
|
+
const needed = new_bump - current_size;
|
|
263
|
+
const pages_needed = (needed + 65535) / 65536; // ceil division
|
|
264
|
+
const result = @wasmMemoryGrow(0, pages_needed);
|
|
265
|
+
if (result == -1) {
|
|
266
|
+
return 0; // Out of memory
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
h.bump_ptr = new_bump;
|
|
271
|
+
h.alloc_count += 1;
|
|
272
|
+
|
|
273
|
+
return aligned;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/// Free a block back to its size class freelist at specific tier.
|
|
277
|
+
/// Attempts to merge with adjacent neighbor blocks (address-based buddy merge).
|
|
278
|
+
fn freeAtTier(offset: u32, sc: SizeClass, tier: usize) void {
|
|
279
|
+
// Try to merge with adjacent blocks if not at max tier
|
|
280
|
+
if (tier + 1 < NUM_TIERS) {
|
|
281
|
+
const block_size = blockSizeForCapacity(sc, tierToCapacity(tier));
|
|
282
|
+
|
|
283
|
+
// Check right neighbor (block at offset + block_size)
|
|
284
|
+
const right_neighbor = offset + block_size;
|
|
285
|
+
if (findAndRemoveByOffset(sc, tier, right_neighbor)) {
|
|
286
|
+
// Merge: this block + right neighbor → parent at offset
|
|
287
|
+
freeAtTierWithMerge(offset, sc, tier + 1);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Check left neighbor (block at offset - block_size)
|
|
292
|
+
if (offset >= block_size) {
|
|
293
|
+
const left_neighbor = offset - block_size;
|
|
294
|
+
if (findAndRemoveByOffset(sc, tier, left_neighbor)) {
|
|
295
|
+
// Merge: left neighbor + this block → parent at left_neighbor
|
|
296
|
+
freeAtTierWithMerge(left_neighbor, sc, tier + 1);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// No merge possible - just push to freelist
|
|
303
|
+
pushToFreelist(offset, sc, tier, false);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/// Free a block after a merge (increments merge count).
|
|
307
|
+
fn freeAtTierWithMerge(offset: u32, sc: SizeClass, tier: usize) void {
|
|
308
|
+
// Try to cascade merge at higher tier
|
|
309
|
+
if (tier + 1 < NUM_TIERS) {
|
|
310
|
+
const block_size = blockSizeForCapacity(sc, tierToCapacity(tier));
|
|
311
|
+
|
|
312
|
+
// Check right neighbor
|
|
313
|
+
const right_neighbor = offset + block_size;
|
|
314
|
+
if (findAndRemoveByOffset(sc, tier, right_neighbor)) {
|
|
315
|
+
freeAtTierWithMerge(offset, sc, tier + 1);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Check left neighbor
|
|
320
|
+
if (offset >= block_size) {
|
|
321
|
+
const left_neighbor = offset - block_size;
|
|
322
|
+
if (findAndRemoveByOffset(sc, tier, left_neighbor)) {
|
|
323
|
+
freeAtTierWithMerge(left_neighbor, sc, tier + 1);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// No further merge - push with merge count increment
|
|
330
|
+
pushToFreelist(offset, sc, tier, true);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/// Push a block onto the freelist with cascading stats.
|
|
334
|
+
fn pushToFreelist(offset: u32, sc: SizeClass, tier: usize, is_merge: bool) void {
|
|
335
|
+
const h = header();
|
|
336
|
+
const old_head = freelistHeadAtTier(sc, tier);
|
|
337
|
+
const free_block = ptrAt(FreeBlock, offset);
|
|
338
|
+
|
|
339
|
+
// Push onto freelist
|
|
340
|
+
free_block.next_ptr = old_head;
|
|
341
|
+
|
|
342
|
+
// Cascading stats: aggregate from old head (if any) + delta
|
|
343
|
+
if (old_head != 0) {
|
|
344
|
+
const old_block = ptrAt(FreeBlock, old_head);
|
|
345
|
+
free_block.freelist_len = old_block.freelist_len + 1;
|
|
346
|
+
free_block.reuse_count = old_block.reuse_count;
|
|
347
|
+
free_block.split_count = old_block.split_count;
|
|
348
|
+
free_block.merge_count = old_block.merge_count + @as(u32, if (is_merge) 1 else 0);
|
|
349
|
+
} else {
|
|
350
|
+
free_block.freelist_len = 1;
|
|
351
|
+
free_block.reuse_count = 0;
|
|
352
|
+
free_block.split_count = 0;
|
|
353
|
+
free_block.merge_count = if (is_merge) 1 else 0;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
setFreelistHeadAtTier(sc, tier, offset);
|
|
357
|
+
h.free_count += 1;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/// Find and remove a block at a specific offset from the freelist.
|
|
361
|
+
/// Returns true if found and removed, false otherwise.
|
|
362
|
+
/// O(n) scan - freelists are expected to be short in practice.
|
|
363
|
+
fn findAndRemoveByOffset(sc: SizeClass, tier: usize, target_offset: u32) bool {
|
|
364
|
+
const head_offset = freelistHeadAtTier(sc, tier);
|
|
365
|
+
if (head_offset == 0) return false;
|
|
366
|
+
|
|
367
|
+
// Check if HEAD is the target
|
|
368
|
+
if (head_offset == target_offset) {
|
|
369
|
+
const head_block = ptrAt(FreeBlock, head_offset);
|
|
370
|
+
setFreelistHeadAtTier(sc, tier, head_block.next_ptr);
|
|
371
|
+
|
|
372
|
+
// Cascade stats to new head
|
|
373
|
+
if (head_block.next_ptr != 0) {
|
|
374
|
+
const new_head = ptrAt(FreeBlock, head_block.next_ptr);
|
|
375
|
+
new_head.freelist_len = head_block.freelist_len - 1;
|
|
376
|
+
new_head.reuse_count = head_block.reuse_count;
|
|
377
|
+
new_head.split_count = head_block.split_count;
|
|
378
|
+
new_head.merge_count = head_block.merge_count;
|
|
379
|
+
}
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Scan freelist for target
|
|
384
|
+
var prev_offset = head_offset;
|
|
385
|
+
var current_offset = ptrAt(FreeBlock, head_offset).next_ptr;
|
|
386
|
+
|
|
387
|
+
while (current_offset != 0) {
|
|
388
|
+
if (current_offset == target_offset) {
|
|
389
|
+
// Found target - remove from list
|
|
390
|
+
const prev_block = ptrAt(FreeBlock, prev_offset);
|
|
391
|
+
const current_block = ptrAt(FreeBlock, current_offset);
|
|
392
|
+
prev_block.next_ptr = current_block.next_ptr;
|
|
393
|
+
|
|
394
|
+
// Update freelist length in head
|
|
395
|
+
const head_block = ptrAt(FreeBlock, freelistHeadAtTier(sc, tier));
|
|
396
|
+
head_block.freelist_len -= 1;
|
|
397
|
+
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
prev_offset = current_offset;
|
|
401
|
+
current_offset = ptrAt(FreeBlock, current_offset).next_ptr;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// =============================================================================
|
|
408
|
+
// Debug exports (temporary for troubleshooting buddy merge)
|
|
409
|
+
// =============================================================================
|
|
410
|
+
|
|
411
|
+
/// Debug: get freelist head offset for a size class at given capacity
|
|
412
|
+
export fn debug_get_freelist_head(size_class: u8, capacity: u32) u32 {
|
|
413
|
+
const sc: SizeClass = @enumFromInt(size_class);
|
|
414
|
+
const tier = capacityToTier(capacity);
|
|
415
|
+
return freelistHeadAtTier(sc, tier);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/// Debug: read next_ptr from a FreeBlock at given offset
|
|
419
|
+
export fn debug_read_next_ptr(offset: u32) u32 {
|
|
420
|
+
if (offset == 0) return 0;
|
|
421
|
+
return ptrAt(FreeBlock, offset).next_ptr;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// =============================================================================
|
|
425
|
+
// JS Imports (for timestamp calculation)
|
|
426
|
+
// =============================================================================
|
|
427
|
+
|
|
428
|
+
extern "env" fn performanceNow() f64;
|
|
429
|
+
extern "env" fn dateNow() f64;
|
|
430
|
+
|
|
431
|
+
// =============================================================================
|
|
432
|
+
// Timestamp Calculation
|
|
433
|
+
// =============================================================================
|
|
434
|
+
|
|
435
|
+
inline fn getTimestampNanos(trace_root_ptr: u32) i64 {
|
|
436
|
+
const root = ptrAt(TraceRoot, trace_root_ptr);
|
|
437
|
+
const current_ms = performanceNow();
|
|
438
|
+
const elapsed_ms = current_ms - root.monotonic_ms;
|
|
439
|
+
const elapsed_nanos: i64 = @intFromFloat(elapsed_ms * 1_000_000.0);
|
|
440
|
+
return root.wall_clock_nanos + elapsed_nanos;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// =============================================================================
|
|
444
|
+
// Exported Functions - Initialization
|
|
445
|
+
// =============================================================================
|
|
446
|
+
|
|
447
|
+
/// Initialize the allocator header. Call once before first allocation.
|
|
448
|
+
/// Idempotent - subsequent calls are no-ops if already initialized.
|
|
449
|
+
export fn init() void {
|
|
450
|
+
const h = header();
|
|
451
|
+
const is_first_init = h.bump_ptr == 0;
|
|
452
|
+
|
|
453
|
+
// Only initialize header on first call
|
|
454
|
+
if (is_first_init) {
|
|
455
|
+
h.bump_ptr = @sizeOf(Header);
|
|
456
|
+
h.alloc_count = 0;
|
|
457
|
+
h.free_count = 0;
|
|
458
|
+
h.span_id_counter = 0;
|
|
459
|
+
|
|
460
|
+
// Clear all freelists (28 capacity-tiered + 1 identity)
|
|
461
|
+
for (&h.freelists) |*fl| {
|
|
462
|
+
fl.* = 0;
|
|
463
|
+
}
|
|
464
|
+
h.freelist_identity = 0;
|
|
465
|
+
}
|
|
466
|
+
// Don't reset thread_id - it persists across init calls
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/// Reset all freelists (for testing/benchmarking).
|
|
470
|
+
/// WARNING: This leaks all allocated blocks. Use free() for proper cleanup.
|
|
471
|
+
export fn reset() void {
|
|
472
|
+
const h = header();
|
|
473
|
+
h.bump_ptr = @sizeOf(Header);
|
|
474
|
+
h.alloc_count = 0;
|
|
475
|
+
h.free_count = 0;
|
|
476
|
+
h.span_id_counter = 0;
|
|
477
|
+
|
|
478
|
+
// Clear all freelists
|
|
479
|
+
for (&h.freelists) |*fl| {
|
|
480
|
+
fl.* = 0;
|
|
481
|
+
}
|
|
482
|
+
h.freelist_identity = 0;
|
|
483
|
+
// Don't reset thread_id - it persists across reset calls
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// =============================================================================
|
|
487
|
+
// Exported Functions - Debug/Stats
|
|
488
|
+
// =============================================================================
|
|
489
|
+
|
|
490
|
+
export fn get_bump_ptr() u32 {
|
|
491
|
+
return header().bump_ptr;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
export fn get_alloc_count() u32 {
|
|
495
|
+
return header().alloc_count;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export fn get_free_count() u32 {
|
|
499
|
+
return header().free_count;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/// Get span system block size for given capacity.
|
|
503
|
+
export fn get_span_system_size(capacity: u32) u32 {
|
|
504
|
+
return blockSizeForCapacity(.span_system, capacity);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/// Get 1-byte column block size for given capacity.
|
|
508
|
+
export fn get_col_1b_size(capacity: u32) u32 {
|
|
509
|
+
return blockSizeForCapacity(.col_1b, capacity);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/// Get 4-byte column block size for given capacity.
|
|
513
|
+
export fn get_col_4b_size(capacity: u32) u32 {
|
|
514
|
+
return blockSizeForCapacity(.col_4b, capacity);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/// Get 8-byte column block size for given capacity.
|
|
518
|
+
export fn get_col_8b_size(capacity: u32) u32 {
|
|
519
|
+
return blockSizeForCapacity(.col_8b, capacity);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// =============================================================================
|
|
523
|
+
// Exported Functions - Thread ID
|
|
524
|
+
// =============================================================================
|
|
525
|
+
|
|
526
|
+
/// Set the thread ID (called once from JS on module init).
|
|
527
|
+
export fn set_thread_id(high: u32, low: u32) void {
|
|
528
|
+
const h = header();
|
|
529
|
+
h.thread_id = (@as(u64, high) << 32) | @as(u64, low);
|
|
530
|
+
h.thread_id_set = 1;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
export fn get_thread_id_high() u32 {
|
|
534
|
+
return @truncate(header().thread_id >> 32);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
export fn get_thread_id_low() u32 {
|
|
538
|
+
return @truncate(header().thread_id);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
export fn is_thread_id_set() u8 {
|
|
542
|
+
return header().thread_id_set;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
export fn get_span_id_counter() u32 {
|
|
546
|
+
return header().span_id_counter;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// =============================================================================
|
|
550
|
+
// Exported Functions - Freelist Statistics
|
|
551
|
+
// =============================================================================
|
|
552
|
+
|
|
553
|
+
/// Get freelist length for a size class at given capacity (O(1) - read from HEAD)
|
|
554
|
+
export fn get_freelist_len(size_class: u8, capacity: u32) u32 {
|
|
555
|
+
const sc: SizeClass = @enumFromInt(size_class);
|
|
556
|
+
const tier = capacityToTier(capacity);
|
|
557
|
+
const head_offset = freelistHeadAtTier(sc, tier);
|
|
558
|
+
if (head_offset == 0) return 0;
|
|
559
|
+
return ptrAt(FreeBlock, head_offset).freelist_len;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/// Get total reuse count for a size class at given capacity (O(1) - read from HEAD)
|
|
563
|
+
export fn get_freelist_reuse_count(size_class: u8, capacity: u32) u32 {
|
|
564
|
+
const sc: SizeClass = @enumFromInt(size_class);
|
|
565
|
+
const tier = capacityToTier(capacity);
|
|
566
|
+
const head_offset = freelistHeadAtTier(sc, tier);
|
|
567
|
+
if (head_offset == 0) return 0;
|
|
568
|
+
return ptrAt(FreeBlock, head_offset).reuse_count;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/// Get split count for a size class at given capacity (O(1) - read from HEAD)
|
|
572
|
+
export fn get_freelist_split_count(size_class: u8, capacity: u32) u32 {
|
|
573
|
+
const sc: SizeClass = @enumFromInt(size_class);
|
|
574
|
+
const tier = capacityToTier(capacity);
|
|
575
|
+
const head_offset = freelistHeadAtTier(sc, tier);
|
|
576
|
+
if (head_offset == 0) return 0;
|
|
577
|
+
return ptrAt(FreeBlock, head_offset).split_count;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/// Get merge count for a size class at given capacity (O(1) - read from HEAD)
|
|
581
|
+
export fn get_freelist_merge_count(size_class: u8, capacity: u32) u32 {
|
|
582
|
+
const sc: SizeClass = @enumFromInt(size_class);
|
|
583
|
+
const tier = capacityToTier(capacity);
|
|
584
|
+
const head_offset = freelistHeadAtTier(sc, tier);
|
|
585
|
+
if (head_offset == 0) return 0;
|
|
586
|
+
return ptrAt(FreeBlock, head_offset).merge_count;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// =============================================================================
|
|
590
|
+
// Exported Functions - Identity Block Operations
|
|
591
|
+
// =============================================================================
|
|
592
|
+
|
|
593
|
+
/// Allocate an identity block (fixed 128 bytes, not capacity-tiered)
|
|
594
|
+
fn allocIdentity() u32 {
|
|
595
|
+
const h = header();
|
|
596
|
+
const head_offset = h.freelist_identity;
|
|
597
|
+
|
|
598
|
+
if (head_offset != 0) {
|
|
599
|
+
// Pop from freelist
|
|
600
|
+
const free_block = ptrAt(FreeBlock, head_offset);
|
|
601
|
+
h.freelist_identity = free_block.next_ptr;
|
|
602
|
+
|
|
603
|
+
if (free_block.next_ptr != 0) {
|
|
604
|
+
ptrAt(FreeBlock, free_block.next_ptr).reuse_count += 1;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
h.alloc_count += 1;
|
|
608
|
+
return head_offset;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// Bump allocate
|
|
612
|
+
const current_bump = h.bump_ptr;
|
|
613
|
+
const aligned = (current_bump + 7) & ~@as(u32, 7);
|
|
614
|
+
const new_bump = aligned + @sizeOf(Identity);
|
|
615
|
+
|
|
616
|
+
h.bump_ptr = new_bump;
|
|
617
|
+
h.alloc_count += 1;
|
|
618
|
+
|
|
619
|
+
return aligned;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/// Free an identity block
|
|
623
|
+
fn freeIdentity(offset: u32) void {
|
|
624
|
+
const h = header();
|
|
625
|
+
const old_head = h.freelist_identity;
|
|
626
|
+
const free_block = ptrAt(FreeBlock, offset);
|
|
627
|
+
|
|
628
|
+
free_block.next_ptr = old_head;
|
|
629
|
+
|
|
630
|
+
if (old_head != 0) {
|
|
631
|
+
const old_block = ptrAt(FreeBlock, old_head);
|
|
632
|
+
free_block.freelist_len = old_block.freelist_len + 1;
|
|
633
|
+
free_block.reuse_count = old_block.reuse_count;
|
|
634
|
+
free_block.split_count = old_block.split_count;
|
|
635
|
+
free_block.merge_count = old_block.merge_count;
|
|
636
|
+
} else {
|
|
637
|
+
free_block.freelist_len = 1;
|
|
638
|
+
free_block.reuse_count = 0;
|
|
639
|
+
free_block.split_count = 0;
|
|
640
|
+
free_block.merge_count = 0;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
h.freelist_identity = offset;
|
|
644
|
+
h.free_count += 1;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/// Allocate identity block and provide offset where JS should write trace_id bytes.
|
|
648
|
+
/// Returns packed u64: (identity_offset << 32) | trace_id_field_offset
|
|
649
|
+
/// JS can write bytes directly to memory[trace_id_field_offset..trace_id_field_offset+len]
|
|
650
|
+
export fn alloc_identity_root_for_js_write(trace_id_len: u32) u64 {
|
|
651
|
+
const max_len = @sizeOf(@TypeOf(@as(Identity, undefined).trace_id));
|
|
652
|
+
if (trace_id_len > max_len) {
|
|
653
|
+
return 0; // trace_id too long
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
const offset = allocIdentity();
|
|
657
|
+
const identity = ptrAt(Identity, offset);
|
|
658
|
+
|
|
659
|
+
// Initialize identity (same as alloc_identity_root)
|
|
660
|
+
const h = header();
|
|
661
|
+
h.span_id_counter += 1;
|
|
662
|
+
identity.span_id = h.span_id_counter;
|
|
663
|
+
identity.write_index = 0;
|
|
664
|
+
identity.trace_id_len = @truncate(trace_id_len);
|
|
665
|
+
|
|
666
|
+
// Calculate absolute byte offset to trace_id field
|
|
667
|
+
// Cast to u32 explicitly to ensure proper type handling
|
|
668
|
+
const field_offset_in_struct: u32 = @offsetOf(Identity, "trace_id");
|
|
669
|
+
const trace_id_field_offset: u32 = offset + field_offset_in_struct;
|
|
670
|
+
|
|
671
|
+
// Pack both offsets into u64: upper 32 bits = identity offset, lower 32 bits = trace_id field offset
|
|
672
|
+
return (@as(u64, offset) << 32) | @as(u64, trace_id_field_offset);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/// Allocate and initialize a CHILD identity block.
|
|
676
|
+
export fn alloc_identity_child() u32 {
|
|
677
|
+
const offset = allocIdentity();
|
|
678
|
+
const identity = ptrAt(Identity, offset);
|
|
679
|
+
|
|
680
|
+
const h = header();
|
|
681
|
+
h.span_id_counter += 1;
|
|
682
|
+
identity.span_id = h.span_id_counter;
|
|
683
|
+
identity.write_index = 0;
|
|
684
|
+
identity.trace_id_len = 0; // Child uses parent's trace_id
|
|
685
|
+
|
|
686
|
+
return offset;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
export fn free_identity(offset: u32) void {
|
|
690
|
+
freeIdentity(offset);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
export fn read_identity_span_id(identity_ptr: u32) u32 {
|
|
694
|
+
return ptrAt(Identity, identity_ptr).span_id;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
export fn read_identity_trace_id_len(identity_ptr: u32) u32 {
|
|
698
|
+
return ptrAt(Identity, identity_ptr).trace_id_len;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
export fn get_identity_trace_id_ptr(identity_ptr: u32) u32 {
|
|
702
|
+
// trace_id starts at offset 9 within Identity struct
|
|
703
|
+
return identity_ptr + @offsetOf(Identity, "trace_id");
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
export fn read_write_index(identity_ptr: u32) u32 {
|
|
707
|
+
return ptrAt(Identity, identity_ptr).write_index;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// =============================================================================
|
|
711
|
+
// Exported Functions - Block Allocation (capacity-aware)
|
|
712
|
+
// =============================================================================
|
|
713
|
+
// Each OpContext may have different capacity, so capacity is passed to each call.
|
|
714
|
+
// Capacity must be a power of 2 between 8 and 512.
|
|
715
|
+
|
|
716
|
+
/// Allocate a span system block (timestamp + entry_type for capacity rows).
|
|
717
|
+
export fn alloc_span_system(capacity: u32) u32 {
|
|
718
|
+
return allocWithCapacity(.span_system, capacity);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/// Free a span system block.
|
|
722
|
+
export fn free_span_system(offset: u32, capacity: u32) void {
|
|
723
|
+
freeWithCapacity(offset, .span_system, capacity);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/// Allocate a 1-byte column block (for enum/boolean).
|
|
727
|
+
export fn alloc_col_1b(capacity: u32) u32 {
|
|
728
|
+
return allocWithCapacity(.col_1b, capacity);
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/// Free a 1-byte column block.
|
|
732
|
+
export fn free_col_1b(offset: u32, capacity: u32) void {
|
|
733
|
+
freeWithCapacity(offset, .col_1b, capacity);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/// Allocate a 4-byte column block (for u32/i32/f32).
|
|
737
|
+
export fn alloc_col_4b(capacity: u32) u32 {
|
|
738
|
+
return allocWithCapacity(.col_4b, capacity);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/// Free a 4-byte column block.
|
|
742
|
+
export fn free_col_4b(offset: u32, capacity: u32) void {
|
|
743
|
+
freeWithCapacity(offset, .col_4b, capacity);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/// Allocate an 8-byte column block (for f64/i64).
|
|
747
|
+
export fn alloc_col_8b(capacity: u32) u32 {
|
|
748
|
+
return allocWithCapacity(.col_8b, capacity);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/// Free an 8-byte column block.
|
|
752
|
+
export fn free_col_8b(offset: u32, capacity: u32) void {
|
|
753
|
+
freeWithCapacity(offset, .col_8b, capacity);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/// Allocate with explicit capacity (converts to tier internally).
|
|
757
|
+
fn allocWithCapacity(sc: SizeClass, capacity: u32) u32 {
|
|
758
|
+
const tier = capacityToTier(capacity);
|
|
759
|
+
return allocAtTier(sc, tier);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/// Free with explicit capacity (converts to tier internally).
|
|
763
|
+
fn freeWithCapacity(offset: u32, sc: SizeClass, capacity: u32) void {
|
|
764
|
+
const tier = capacityToTier(capacity);
|
|
765
|
+
freeAtTier(offset, sc, tier);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// =============================================================================
|
|
769
|
+
// Exported Functions - TraceRoot Operations
|
|
770
|
+
// =============================================================================
|
|
771
|
+
|
|
772
|
+
/// Initialize a TraceRoot at the given offset.
|
|
773
|
+
/// Sets wall clock and monotonic start times for timestamp calculation.
|
|
774
|
+
export fn init_trace_root(trace_root_ptr: u32) void {
|
|
775
|
+
const root = ptrAt(TraceRoot, trace_root_ptr);
|
|
776
|
+
const ms: i64 = @intFromFloat(dateNow());
|
|
777
|
+
root.wall_clock_nanos = ms * 1_000_000;
|
|
778
|
+
root.monotonic_ms = performanceNow();
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// =============================================================================
|
|
782
|
+
// Exported Functions - Span Lifecycle
|
|
783
|
+
// =============================================================================
|
|
784
|
+
|
|
785
|
+
/// Write span-start to a Span System block.
|
|
786
|
+
/// Sets row 0 (span-start) and row 1 (span-exception placeholder).
|
|
787
|
+
/// Sets write_index = 2 in identity block.
|
|
788
|
+
export fn span_start(system_ptr: u32, identity_ptr: u32, trace_root_ptr: u32, capacity: u32) void {
|
|
789
|
+
const base = bytesAt(system_ptr);
|
|
790
|
+
|
|
791
|
+
// Span system layout: [timestamp: i64 × capacity][entry_type: u8 × capacity]
|
|
792
|
+
const ts_ptr: [*]allowzero i64 = @ptrCast(@alignCast(base));
|
|
793
|
+
const et_ptr: [*]allowzero u8 = base + capacity * 8;
|
|
794
|
+
|
|
795
|
+
// Row 0: span-start
|
|
796
|
+
ts_ptr[0] = getTimestampNanos(trace_root_ptr);
|
|
797
|
+
et_ptr[0] = ENTRY_TYPE_SPAN_START;
|
|
798
|
+
|
|
799
|
+
// Row 1: pre-initialize as span-exception
|
|
800
|
+
ts_ptr[1] = 0;
|
|
801
|
+
et_ptr[1] = ENTRY_TYPE_SPAN_EXCEPTION;
|
|
802
|
+
|
|
803
|
+
// Set write_index = 2
|
|
804
|
+
ptrAt(Identity, identity_ptr).write_index = 2;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/// Write span-ok to row 1 (successful completion).
|
|
808
|
+
export fn span_end_ok(system_ptr: u32, trace_root_ptr: u32, capacity: u32) void {
|
|
809
|
+
const base = bytesAt(system_ptr);
|
|
810
|
+
const ts_ptr: [*]allowzero i64 = @ptrCast(@alignCast(base));
|
|
811
|
+
const et_ptr: [*]allowzero u8 = base + capacity * 8;
|
|
812
|
+
|
|
813
|
+
et_ptr[1] = ENTRY_TYPE_SPAN_OK;
|
|
814
|
+
ts_ptr[1] = getTimestampNanos(trace_root_ptr);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/// Write span-err to row 1 (error result, not exception).
|
|
818
|
+
export fn span_end_err(system_ptr: u32, trace_root_ptr: u32, capacity: u32) void {
|
|
819
|
+
const base = bytesAt(system_ptr);
|
|
820
|
+
const ts_ptr: [*]allowzero i64 = @ptrCast(@alignCast(base));
|
|
821
|
+
const et_ptr: [*]allowzero u8 = base + capacity * 8;
|
|
822
|
+
|
|
823
|
+
et_ptr[1] = ENTRY_TYPE_SPAN_ERR;
|
|
824
|
+
ts_ptr[1] = getTimestampNanos(trace_root_ptr);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/// Write a log entry (info/debug/warn/error).
|
|
828
|
+
/// Bumps write_index, writes timestamp+entry_type, returns the idx written to.
|
|
829
|
+
/// SpanLogger uses returned idx for string column writes.
|
|
830
|
+
export fn write_log_entry(system_ptr: u32, identity_ptr: u32, trace_root_ptr: u32, entry_type: u8, capacity: u32) u32 {
|
|
831
|
+
const identity = ptrAt(Identity, identity_ptr);
|
|
832
|
+
const idx = identity.write_index;
|
|
833
|
+
|
|
834
|
+
const base = bytesAt(system_ptr);
|
|
835
|
+
const ts_ptr: [*]allowzero i64 = @ptrCast(@alignCast(base));
|
|
836
|
+
const et_ptr: [*]allowzero u8 = base + capacity * 8;
|
|
837
|
+
|
|
838
|
+
ts_ptr[idx] = getTimestampNanos(trace_root_ptr);
|
|
839
|
+
et_ptr[idx] = entry_type;
|
|
840
|
+
|
|
841
|
+
identity.write_index = idx + 1;
|
|
842
|
+
return idx;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// =============================================================================
|
|
846
|
+
// Exported Functions - Column Write Operations
|
|
847
|
+
// =============================================================================
|
|
848
|
+
|
|
849
|
+
/// Write an f64 value to a column.
|
|
850
|
+
/// Returns: column offset (same as input if already allocated, or newly allocated)
|
|
851
|
+
export fn write_col_f64(col_offset: u32, row_idx: u32, value: f64, capacity: u32) u32 {
|
|
852
|
+
var offset = col_offset;
|
|
853
|
+
if (offset == 0) {
|
|
854
|
+
offset = allocWithCapacity(.col_8b, capacity);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
const base = bytesAt(offset);
|
|
858
|
+
const null_bitmap_size = (capacity + 7) >> 3;
|
|
859
|
+
|
|
860
|
+
// Write value (after null bitmap)
|
|
861
|
+
const val_ptr: *allowzero align(1) f64 = @ptrCast(base + null_bitmap_size + row_idx * 8);
|
|
862
|
+
val_ptr.* = value;
|
|
863
|
+
|
|
864
|
+
// Set null bit (mark as valid)
|
|
865
|
+
base[row_idx >> 3] |= @as(u8, 1) << @intCast(row_idx & 7);
|
|
866
|
+
|
|
867
|
+
return offset;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/// Write a u32 value to a column.
|
|
871
|
+
/// Returns: column offset (same as input if already allocated, or newly allocated)
|
|
872
|
+
export fn write_col_u32(col_offset: u32, row_idx: u32, value: u32, capacity: u32) u32 {
|
|
873
|
+
var offset = col_offset;
|
|
874
|
+
if (offset == 0) {
|
|
875
|
+
offset = allocWithCapacity(.col_4b, capacity);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
const base = bytesAt(offset);
|
|
879
|
+
const null_bitmap_size = (capacity + 7) >> 3;
|
|
880
|
+
const val_ptr: *allowzero align(1) u32 = @ptrCast(base + null_bitmap_size + row_idx * 4);
|
|
881
|
+
val_ptr.* = value;
|
|
882
|
+
base[row_idx >> 3] |= @as(u8, 1) << @intCast(row_idx & 7);
|
|
883
|
+
|
|
884
|
+
return offset;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/// Write a u8 value to a column (for enum/boolean).
|
|
888
|
+
/// Returns: column offset (same as input if already allocated, or newly allocated)
|
|
889
|
+
export fn write_col_u8(col_offset: u32, row_idx: u32, value: u8, capacity: u32) u32 {
|
|
890
|
+
var offset = col_offset;
|
|
891
|
+
if (offset == 0) {
|
|
892
|
+
offset = allocWithCapacity(.col_1b, capacity);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
const base = bytesAt(offset);
|
|
896
|
+
const null_bitmap_size = (capacity + 7) >> 3;
|
|
897
|
+
base[null_bitmap_size + row_idx] = value;
|
|
898
|
+
base[row_idx >> 3] |= @as(u8, 1) << @intCast(row_idx & 7);
|
|
899
|
+
|
|
900
|
+
return offset;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// =============================================================================
|
|
904
|
+
// Exported Functions - Debug/Read Operations
|
|
905
|
+
// =============================================================================
|
|
906
|
+
|
|
907
|
+
/// Get current performance.now() value (for debugging).
|
|
908
|
+
export fn get_performance_now() f64 {
|
|
909
|
+
return performanceNow();
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
/// Compute a timestamp relative to trace root (for debugging).
|
|
913
|
+
export fn debug_compute_timestamp(trace_root_ptr: u32) i64 {
|
|
914
|
+
return getTimestampNanos(trace_root_ptr);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
/// Read timestamp at given row from a Span System block.
|
|
918
|
+
export fn read_timestamp(system_ptr: u32, row_idx: u32) i64 {
|
|
919
|
+
const base = bytesAt(system_ptr);
|
|
920
|
+
const ts_ptr: [*]allowzero const i64 = @ptrCast(@alignCast(base));
|
|
921
|
+
return ts_ptr[row_idx];
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
/// Read entry_type at given row from a Span System block.
|
|
925
|
+
export fn read_entry_type(system_ptr: u32, row_idx: u32, capacity: u32) u8 {
|
|
926
|
+
const base = bytesAt(system_ptr);
|
|
927
|
+
const et_ptr: [*]allowzero const u8 = base + capacity * 8;
|
|
928
|
+
return et_ptr[row_idx];
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/// Read f64 value from a column.
|
|
932
|
+
export fn read_col_f64(col_offset: u32, row_idx: u32, capacity: u32) f64 {
|
|
933
|
+
const base = bytesAt(col_offset);
|
|
934
|
+
const null_bitmap_size = (capacity + 7) >> 3;
|
|
935
|
+
const val_ptr: *allowzero align(1) const f64 = @ptrCast(base + null_bitmap_size + row_idx * 8);
|
|
936
|
+
return val_ptr.*;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
/// Check if null bit is set for a row (1 = valid, 0 = null).
|
|
940
|
+
export fn read_col_is_valid(col_offset: u32, row_idx: u32) u8 {
|
|
941
|
+
const base = bytesAt(col_offset);
|
|
942
|
+
const byte = base[row_idx >> 3];
|
|
943
|
+
const bit: u8 = @as(u8, 1) << @intCast(row_idx & 7);
|
|
944
|
+
return if ((byte & bit) != 0) 1 else 0;
|
|
945
|
+
}
|