@smoothbricks/lmao 0.2.2 → 0.2.3
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/dist/allocator.wasm +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/JsBufferStrategy.d.ts +4 -3
- package/dist/lib/JsBufferStrategy.d.ts.map +1 -1
- package/dist/lib/JsBufferStrategy.js +18 -11
- package/dist/lib/arrow/lease.d.ts +10 -0
- package/dist/lib/arrow/lease.d.ts.map +1 -0
- package/dist/lib/arrow/lease.js +33 -0
- package/dist/lib/arrow/utils.d.ts +3 -4
- package/dist/lib/arrow/utils.d.ts.map +1 -1
- package/dist/lib/arrow/utils.js +12 -13
- package/dist/lib/arrow/vocabularyDictionary.d.ts +21 -0
- package/dist/lib/arrow/vocabularyDictionary.d.ts.map +1 -0
- package/dist/lib/arrow/vocabularyDictionary.js +95 -0
- package/dist/lib/bufferStrategy.d.ts +3 -2
- package/dist/lib/bufferStrategy.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.js +3 -2
- package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/evaluatorGenerator.js +12 -11
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +44 -82
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/fixedPositionWriterGenerator.js +223 -162
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts +63 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts.map +1 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.js +447 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts +36 -19
- package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/spanLoggerGenerator.js +164 -158
- package/dist/lib/convertToArrow.d.ts +7 -2
- package/dist/lib/convertToArrow.d.ts.map +1 -1
- package/dist/lib/convertToArrow.js +499 -285
- package/dist/lib/defineOpContext.js +1 -1
- package/dist/lib/enumMetadata.d.ts +19 -0
- package/dist/lib/enumMetadata.d.ts.map +1 -0
- package/dist/lib/enumMetadata.js +86 -0
- package/dist/lib/flushScheduler.d.ts.map +1 -1
- package/dist/lib/flushScheduler.js +13 -4
- package/dist/lib/library.d.ts +16 -98
- package/dist/lib/library.d.ts.map +1 -1
- package/dist/lib/library.js +32 -525
- package/dist/lib/logBinding.d.ts +21 -27
- package/dist/lib/logBinding.d.ts.map +1 -1
- package/dist/lib/op.d.ts +30 -30
- package/dist/lib/op.d.ts.map +1 -1
- package/dist/lib/op.js +15 -22
- package/dist/lib/opContext/createOpGroup.d.ts +1 -1
- package/dist/lib/opContext/createOpGroup.d.ts.map +1 -1
- package/dist/lib/opContext/createOpGroup.js +22 -29
- package/dist/lib/opContext/defineOp.d.ts +4 -4
- package/dist/lib/opContext/defineOp.d.ts.map +1 -1
- package/dist/lib/opContext/defineOp.js +53 -10
- package/dist/lib/opContext/opGroupTypes.d.ts +2 -2
- package/dist/lib/opContext/opTypes.d.ts +1 -1
- package/dist/lib/opContext/opTypes.d.ts.map +1 -1
- package/dist/lib/opContext/spanContextTypes.d.ts +29 -14
- package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -1
- package/dist/lib/opContext/types.d.ts +4 -4
- package/dist/lib/opContext/types.d.ts.map +1 -1
- package/dist/lib/physicalLayoutPlan.d.ts +89 -0
- package/dist/lib/physicalLayoutPlan.d.ts.map +1 -0
- package/dist/lib/physicalLayoutPlan.js +442 -0
- package/dist/lib/resolveMessage.d.ts +9 -0
- package/dist/lib/resolveMessage.d.ts.map +1 -0
- package/dist/lib/resolveMessage.js +63 -0
- package/dist/lib/result.d.ts +5 -7
- package/dist/lib/result.d.ts.map +1 -1
- package/dist/lib/result.js +19 -26
- package/dist/lib/runtimeHint.d.ts +35 -0
- package/dist/lib/runtimeHint.d.ts.map +1 -0
- package/dist/lib/runtimeHint.js +79 -0
- package/dist/lib/schema/types.d.ts +1 -1
- package/dist/lib/schema/types.d.ts.map +1 -1
- package/dist/lib/span-buffer/aot/v1.d.ts +2 -0
- package/dist/lib/span-buffer/aot/v1.d.ts.map +1 -0
- package/dist/lib/span-buffer/aot/v1.js +24 -0
- package/dist/lib/spanBuffer.d.ts +33 -4
- package/dist/lib/spanBuffer.d.ts.map +1 -1
- package/dist/lib/spanBuffer.js +583 -91
- package/dist/lib/spanBufferStats.d.ts +1 -1
- package/dist/lib/spanBufferStats.d.ts.map +1 -1
- package/dist/lib/spanContext.d.ts +27 -51
- package/dist/lib/spanContext.d.ts.map +1 -1
- package/dist/lib/spanContext.js +822 -344
- package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
- package/dist/lib/sqlite/sqlite-common.js +20 -21
- package/dist/lib/testing/bun-harness.d.ts +8 -3
- package/dist/lib/testing/bun-harness.d.ts.map +1 -1
- package/dist/lib/testing/bun-harness.js +30 -18
- package/dist/lib/testing/extractFacts.d.ts +1 -1
- package/dist/lib/testing/extractFacts.d.ts.map +1 -1
- package/dist/lib/testing/extractFacts.js +55 -63
- package/dist/lib/testing/facts.d.ts +1 -1
- package/dist/lib/testing/facts.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.d.ts +1 -1
- package/dist/lib/testing/queryable-span.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.js +26 -28
- package/dist/lib/testing/span-query.d.ts.map +1 -1
- package/dist/lib/testing/span-query.js +19 -22
- package/dist/lib/testing/stdio-replay.d.ts.map +1 -1
- package/dist/lib/testing/stdio-replay.js +19 -8
- package/dist/lib/threadId.d.ts.map +1 -1
- package/dist/lib/threadId.js +6 -3
- package/dist/lib/traceRoot.d.ts +30 -8
- package/dist/lib/traceRoot.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.d.ts +17 -15
- package/dist/lib/traceRoot.es.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.js +68 -34
- package/dist/lib/traceRoot.js +11 -0
- package/dist/lib/traceRoot.node.d.ts +17 -19
- package/dist/lib/traceRoot.node.d.ts.map +1 -1
- package/dist/lib/traceRoot.node.js +66 -38
- package/dist/lib/traceTopology.d.ts +42 -0
- package/dist/lib/traceTopology.d.ts.map +1 -0
- package/dist/lib/traceTopology.js +260 -0
- package/dist/lib/tracer.d.ts +9 -5
- package/dist/lib/tracer.d.ts.map +1 -1
- package/dist/lib/tracer.js +65 -71
- package/dist/lib/tracers/ArrayQueueTracer.d.ts +1 -1
- package/dist/lib/tracers/ArrayQueueTracer.js +1 -1
- package/dist/lib/tracers/StdioTracer.d.ts.map +1 -1
- package/dist/lib/tracers/StdioTracer.js +15 -13
- package/dist/lib/tracers/TestTracer.d.ts +4 -6
- package/dist/lib/tracers/TestTracer.d.ts.map +1 -1
- package/dist/lib/tracers/TestTracer.js +6 -8
- package/dist/lib/types.d.ts +49 -32
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/vocabularyRegistry.d.ts +25 -0
- package/dist/lib/vocabularyRegistry.d.ts.map +1 -0
- package/dist/lib/vocabularyRegistry.js +372 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts +6 -10
- package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -1
- package/dist/lib/wasm/WasmBufferStrategy.js +44 -37
- package/dist/lib/wasm/wasmAllocator.d.ts +27 -22
- package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -1
- package/dist/lib/wasm/wasmAllocator.js +66 -44
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts +67 -0
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts.map +1 -0
- package/dist/lib/wasm/wasmPhysicalLayout.js +179 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts +79 -31
- package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -1
- package/dist/lib/wasm/wasmSpanBuffer.js +442 -272
- package/dist/lib/wasm/wasmTraceRoot.d.ts +24 -22
- package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -1
- package/dist/lib/wasm/wasmTraceRoot.js +110 -71
- package/dist/vocabulary/register/v1.d.ts +2 -0
- package/dist/vocabulary/register/v1.d.ts.map +1 -0
- package/dist/vocabulary/register/v1.js +1 -0
- package/dist/wasm.d.ts +5 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +4 -0
- package/package.json +54 -6
- package/src/index.ts +1 -0
- package/src/lib/JsBufferStrategy.ts +27 -9
- package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +335 -37
- package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +97 -26
- package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +75 -15
- package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +30 -6
- package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +18 -21
- package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +5 -2
- package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +25 -7
- package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +3 -2
- package/src/lib/__tests__/buffer-overflow.test.ts +24 -18
- package/src/lib/__tests__/capability-span-context.test.ts +505 -0
- package/src/lib/__tests__/capacity-tuning.test.ts +5 -3
- package/src/lib/__tests__/eager-columns.test.ts +345 -0
- package/src/lib/__tests__/enum-metadata-aot.test.ts +153 -0
- package/src/lib/__tests__/enum-metadata.test.ts +177 -0
- package/src/lib/__tests__/fixtures/empty-vocabulary-runtime.fixture.ts +15 -0
- package/src/lib/__tests__/flushScheduler.test.ts +5 -1
- package/src/lib/__tests__/identity-view.property.test.ts +179 -0
- package/src/lib/__tests__/library.test.ts +19 -235
- package/src/lib/__tests__/message-buffer-families.test.ts +878 -0
- package/src/lib/__tests__/nested-library-tasks.test.ts +14 -15
- package/src/lib/__tests__/op-metadata.test.ts +1 -1
- package/src/lib/__tests__/op-type-safety.test.ts +5 -16
- package/src/lib/__tests__/physical-layout-plan.test.ts +333 -0
- package/src/lib/__tests__/remap-descriptor-integration.test.ts +381 -0
- package/src/lib/__tests__/root-context-construction.test.ts +414 -0
- package/src/lib/__tests__/span-auto-runtime.test.ts +386 -0
- package/src/lib/__tests__/span-buffer-segment-stats.test.ts +221 -0
- package/src/lib/__tests__/span-lifecycle.test.ts +53 -25
- package/src/lib/__tests__/spanbuffer-materializer-parity.test.ts +266 -0
- package/src/lib/__tests__/sync-async-trace.test.ts +24 -23
- package/src/lib/__tests__/tag-writer-aot.test.ts +214 -0
- package/src/lib/__tests__/test-helpers.ts +67 -12
- package/src/lib/__tests__/threadId.test.ts +62 -0
- package/src/lib/__tests__/timestamp.test.ts +221 -93
- package/src/lib/__tests__/traceTopology.property.test.ts +383 -0
- package/src/lib/__tests__/type-narrowing.test.ts +63 -0
- package/src/lib/__tests__/vocabulary-dense-decoding.test.ts +405 -0
- package/src/lib/__tests__/vocabularyRegistry.test.ts +313 -0
- package/src/lib/arrow/lease.ts +43 -0
- package/src/lib/arrow/utils.ts +10 -14
- package/src/lib/arrow/vocabularyDictionary.ts +123 -0
- package/src/lib/bufferStrategy.ts +9 -1
- package/src/lib/cloudflare/traceRows.ts +3 -2
- package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +21 -141
- package/src/lib/codegen/__tests__/fixedPositionWriter-parity.test.ts +273 -0
- package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +61 -34
- package/src/lib/codegen/__tests__/nullBitmap.test.ts +33 -37
- package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +34 -18
- package/src/lib/codegen/__tests__/spanLoggerMaterializerParity.test.ts +503 -0
- package/src/lib/codegen/evaluatorGenerator.ts +18 -13
- package/src/lib/codegen/fixedPositionWriterGenerator.ts +329 -245
- package/src/lib/codegen/spanLoggerClosureMaterializer.ts +598 -0
- package/src/lib/codegen/spanLoggerGenerator.ts +241 -177
- package/src/lib/convertToArrow.ts +598 -311
- package/src/lib/defineOpContext.ts +1 -1
- package/src/lib/enumMetadata.ts +121 -0
- package/src/lib/flushScheduler.ts +11 -5
- package/src/lib/library.ts +37 -595
- package/src/lib/logBinding.ts +21 -27
- package/src/lib/op.ts +75 -18
- package/src/lib/opContext/__tests__/retry.test.ts +27 -21
- package/src/lib/opContext/createOpGroup.ts +33 -31
- package/src/lib/opContext/defineOp.ts +88 -11
- package/src/lib/opContext/opGroupTypes.ts +2 -2
- package/src/lib/opContext/opTypes.ts +1 -1
- package/src/lib/opContext/spanContextTypes.ts +98 -17
- package/src/lib/opContext/types.ts +7 -3
- package/src/lib/physicalLayoutPlan.ts +598 -0
- package/src/lib/resolveMessage.ts +67 -0
- package/src/lib/result.ts +20 -33
- package/src/lib/runtimeHint.ts +98 -0
- package/src/lib/schema/__tests__/featureFlags.test.ts +2 -1
- package/src/lib/schema/builder.ts +1 -1
- package/src/lib/schema/types.ts +1 -1
- package/src/lib/span-buffer/aot/v1.ts +26 -0
- package/src/lib/spanBuffer.ts +658 -92
- package/src/lib/spanBufferStats.ts +1 -1
- package/src/lib/spanContext.ts +1350 -861
- package/src/lib/sqlite/sqlite-common.ts +20 -31
- package/src/lib/testing/__tests__/topology-traversal.test.ts +174 -0
- package/src/lib/testing/__tests__/vitest-harness.test.ts +2 -1
- package/src/lib/testing/bun-harness.ts +94 -43
- package/src/lib/testing/extractFacts.ts +64 -78
- package/src/lib/testing/facts.ts +1 -1
- package/src/lib/testing/queryable-span.ts +23 -30
- package/src/lib/testing/span-query.ts +16 -20
- package/src/lib/testing/stdio-replay.ts +25 -8
- package/src/lib/testing/vitest-harness.ts +1 -1
- package/src/lib/threadId.ts +6 -3
- package/src/lib/traceRoot.es.ts +77 -42
- package/src/lib/traceRoot.node.ts +75 -46
- package/src/lib/traceRoot.ts +41 -14
- package/src/lib/traceTopology.ts +279 -0
- package/src/lib/tracer.ts +109 -98
- package/src/lib/tracers/ArrayQueueTracer.ts +1 -1
- package/src/lib/tracers/StdioTracer.ts +15 -13
- package/src/lib/tracers/TestTracer.ts +6 -8
- package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +15 -10
- package/src/lib/tracers/__tests__/TestTracer.test.ts +23 -13
- package/src/lib/types.ts +64 -33
- package/src/lib/vocabularyRegistry.ts +439 -0
- package/src/lib/wasm/WasmBufferStrategy.ts +56 -48
- package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +215 -11
- package/src/lib/wasm/__tests__/allocatorFreeBlockClamp.test.ts +86 -0
- package/src/lib/wasm/__tests__/wasm-identity-view.test.ts +311 -0
- package/src/lib/wasm/__tests__/wasm-integration.test.ts +417 -44
- package/src/lib/wasm/__tests__/wasm-message-buffer-families.test.ts +588 -0
- package/src/lib/wasm/__tests__/wasmAllocator.test.ts +100 -668
- package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +419 -63
- package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +24 -29
- package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +2 -2
- package/src/lib/wasm/wasmAllocator.ts +131 -96
- package/src/lib/wasm/wasmPhysicalLayout.ts +309 -0
- package/src/lib/wasm/wasmSpanBuffer.ts +597 -341
- package/src/lib/wasm/wasmTraceRoot.ts +140 -78
- package/src/vocabulary/register/v1.ts +1 -0
- package/src/wasm.ts +19 -0
- package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +0 -319
- package/src/lib/__tests__/remapped-buffer-view.test.ts +0 -635
- package/src/lib/wasm/allocator.zig +0 -948
|
@@ -14,11 +14,24 @@ import type { ColumnValueType } from '@smoothbricks/arrow-builder';
|
|
|
14
14
|
import { getSchemaType } from '@smoothbricks/arrow-builder';
|
|
15
15
|
import { checkCapacityTuning } from '../capacityTuning.js';
|
|
16
16
|
import type { OpMetadata } from '../op.js';
|
|
17
|
+
import type { EagerColumnDescriptor } from '../physicalLayoutPlan.js';
|
|
18
|
+
import type { MessageLayoutFamily, MessagePhysicalLayout } from '../runtimeHint.js';
|
|
17
19
|
import type { LogSchema } from '../schema/LogSchema.js';
|
|
18
20
|
import type { SpanBufferStats } from '../spanBufferStats.js';
|
|
19
21
|
import type { ITraceRoot } from '../traceRoot.js';
|
|
20
|
-
import type {
|
|
21
|
-
import type
|
|
22
|
+
import type { SpanBuffer } from '../types.js';
|
|
23
|
+
import { getVocabularyGeneration, type VocabularyGeneration } from '../vocabularyRegistry.js';
|
|
24
|
+
import {
|
|
25
|
+
WASM_NO_LAYOUT_OFFSET,
|
|
26
|
+
WASM_SPAN_IDENTITY_CHILD,
|
|
27
|
+
WASM_SPAN_IDENTITY_ROOT,
|
|
28
|
+
type WasmAllocator,
|
|
29
|
+
} from './wasmAllocator.js';
|
|
30
|
+
import {
|
|
31
|
+
getWasmPhysicalLayout,
|
|
32
|
+
type WasmNumericFamily,
|
|
33
|
+
type WasmPhysicalLayoutDescriptor,
|
|
34
|
+
} from './wasmPhysicalLayout.js';
|
|
22
35
|
|
|
23
36
|
// Spec link (88): realizes specs/lmao/01q_wasm_memory_architecture.md#smoo/lmao!n/wasm-mem (SpanBuffer + SpanLogger codegen).
|
|
24
37
|
//#region smoo/lmao!n/wasm-mem.spanbuffer
|
|
@@ -33,45 +46,95 @@ import type { WasmAllocator } from './wasmAllocator.js';
|
|
|
33
46
|
* Internal fields (_traceRoot, _scopeValues, _opMetadata, _callsiteMetadata) are passed separately
|
|
34
47
|
* by the create* functions.
|
|
35
48
|
*/
|
|
36
|
-
export
|
|
49
|
+
export type WasmBufferState = 'live' | 'freed';
|
|
50
|
+
export type WasmIdentityMode = 'root' | 'child' | 'overflow';
|
|
51
|
+
|
|
52
|
+
export interface WasmBufferDescriptor {
|
|
53
|
+
readonly generation: number;
|
|
54
|
+
readonly kind: WasmIdentityMode;
|
|
55
|
+
state: WasmBufferState;
|
|
56
|
+
readonly layout: WasmPhysicalLayoutDescriptor;
|
|
57
|
+
readonly allocationPtr: number;
|
|
58
|
+
readonly allocationByteLength: number;
|
|
59
|
+
readonly systemPtr: number;
|
|
60
|
+
readonly familyPtrs: Readonly<Record<WasmNumericFamily, number>>;
|
|
61
|
+
readonly identityPtr: number;
|
|
62
|
+
readonly ownsIdentity: boolean;
|
|
63
|
+
memoryVersion: number;
|
|
64
|
+
readonly parent?: WasmBufferDescriptor;
|
|
65
|
+
overflow?: WasmBufferDescriptor;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const EMPTY_EAGER_COLUMNS: EagerColumnDescriptor = Object.freeze({
|
|
69
|
+
names: Object.freeze([]),
|
|
70
|
+
words: Object.freeze([]),
|
|
71
|
+
key: '',
|
|
72
|
+
});
|
|
73
|
+
let nextWasmBufferGeneration = 0;
|
|
74
|
+
|
|
75
|
+
export interface WasmSpanBufferOptions<T extends LogSchema = LogSchema> {
|
|
37
76
|
allocator: WasmAllocator;
|
|
38
77
|
capacity: number;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
parent_span_id?: number;
|
|
44
|
-
logSchema: LogSchema;
|
|
45
|
-
_traceRoot: ITraceRoot;
|
|
78
|
+
messageLayoutFamily?: MessageLayoutFamily;
|
|
79
|
+
messagePhysicalLayout?: MessagePhysicalLayout;
|
|
80
|
+
logSchema: T;
|
|
81
|
+
_traceRoot: ITraceRoot<T>;
|
|
46
82
|
_scopeValues: Readonly<Record<string, unknown>>;
|
|
47
83
|
_opMetadata: OpMetadata;
|
|
48
84
|
_callsiteMetadata: OpMetadata;
|
|
85
|
+
_vocabularyGeneration: VocabularyGeneration;
|
|
86
|
+
_layout: WasmPhysicalLayoutDescriptor;
|
|
87
|
+
_identityMode?: WasmIdentityMode;
|
|
88
|
+
_identitySource?: WasmSpanBufferInstance<T>;
|
|
89
|
+
_parent?: WasmSpanBufferInstance<T>;
|
|
90
|
+
_generation?: number;
|
|
49
91
|
}
|
|
50
92
|
|
|
51
93
|
/**
|
|
52
|
-
*
|
|
53
|
-
* Extends AnySpanBuffer with WASM-specific pointer properties.
|
|
94
|
+
* Extends the schema-specific SpanBuffer shape with WASM pointer ownership.
|
|
54
95
|
*/
|
|
55
|
-
export
|
|
96
|
+
export type WasmSpanBufferInstance<T extends LogSchema = LogSchema> = SpanBuffer<T> & {
|
|
56
97
|
// ===========================================================================
|
|
57
98
|
// WASM pointers (internal implementation details)
|
|
58
99
|
// ===========================================================================
|
|
59
100
|
/** Byte offset into WASM memory for system columns (timestamp + entry_type) */
|
|
60
101
|
readonly _systemPtr: number;
|
|
102
|
+
/** Owning root/child/overflow superblock returned by the allocator. */
|
|
103
|
+
readonly _allocationPtr: number;
|
|
104
|
+
readonly _allocationByteLength: number;
|
|
61
105
|
/** Byte offset into WASM memory for identity block (writeIndex, span_id, trace_id) */
|
|
62
106
|
readonly _identityPtr: number;
|
|
63
107
|
/** Array of byte offsets for each column (-1 = not allocated) */
|
|
64
108
|
readonly _columnPtrs: Int32Array;
|
|
65
109
|
/** Reference to the WASM allocator */
|
|
66
110
|
readonly _allocator: WasmAllocator;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
111
|
+
readonly _descriptor: WasmBufferDescriptor;
|
|
112
|
+
readonly _layout: WasmPhysicalLayoutDescriptor;
|
|
113
|
+
readonly _familyPtrs: Readonly<Record<WasmNumericFamily, number>>;
|
|
114
|
+
_viewVersion: number;
|
|
115
|
+
_timestampView: BigInt64Array;
|
|
116
|
+
_entryTypeView?: Uint8Array;
|
|
117
|
+
_messageIds?: Uint16Array;
|
|
118
|
+
_logHeaders?: Uint32Array;
|
|
119
|
+
_rowHeaders?: Uint32Array;
|
|
120
|
+
_identityView: Uint8Array;
|
|
121
|
+
_identityData: DataView;
|
|
122
|
+
_identitySource?: WasmSpanBufferInstance<T>;
|
|
123
|
+
readonly _threadId: bigint;
|
|
124
|
+
readonly _spanId: number;
|
|
125
|
+
_refreshViews(version: number): void;
|
|
126
|
+
_ensureWasmViews(): void;
|
|
127
|
+
_getWasmColumnValue(columnIndex: number): ColumnValueType | undefined;
|
|
128
|
+
_getWasmColumnNulls(columnIndex: number): Uint8Array | undefined;
|
|
129
|
+
readonly _identityOwner: boolean;
|
|
130
|
+
_overflowWriteIndex: number;
|
|
131
|
+
|
|
132
|
+
// Preserve WASM-typed parent and overflow links.
|
|
133
|
+
_parent?: WasmSpanBufferInstance<T>;
|
|
134
|
+
_overflow?: WasmSpanBufferInstance<T>;
|
|
135
|
+
|
|
136
|
+
// Present only for dynamic-only and mixed physical families.
|
|
137
|
+
readonly _message?: string[];
|
|
75
138
|
|
|
76
139
|
// ===========================================================================
|
|
77
140
|
// WASM-specific methods
|
|
@@ -87,15 +150,21 @@ export interface WasmSpanBufferInstance extends AnySpanBuffer {
|
|
|
87
150
|
|
|
88
151
|
/** Get column nulls array if allocated */
|
|
89
152
|
getNullsIfAllocated(columnName: string): Uint8Array | undefined;
|
|
90
|
-
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
type WasmRawMessageBuffer = WasmSpanBufferInstance & { readonly _message: string[] };
|
|
156
|
+
type WasmUnpackedMessageBuffer = WasmSpanBufferInstance & { readonly _entryTypeView: Uint8Array };
|
|
91
157
|
|
|
92
158
|
/**
|
|
93
159
|
* Constructor type for generated WASM SpanBuffer classes.
|
|
94
160
|
*/
|
|
95
|
-
export interface WasmSpanBufferConstructor {
|
|
96
|
-
new (opts: WasmSpanBufferOptions): WasmSpanBufferInstance
|
|
97
|
-
readonly schema:
|
|
98
|
-
|
|
161
|
+
export interface WasmSpanBufferConstructor<T extends LogSchema = LogSchema> {
|
|
162
|
+
new (opts: WasmSpanBufferOptions<T>): WasmSpanBufferInstance<T>;
|
|
163
|
+
readonly schema: T;
|
|
164
|
+
readonly messageLayoutFamily: MessageLayoutFamily;
|
|
165
|
+
readonly messagePhysicalLayout: MessagePhysicalLayout;
|
|
166
|
+
readonly eagerColumns: EagerColumnDescriptor;
|
|
167
|
+
stats: SpanBufferStats;
|
|
99
168
|
}
|
|
100
169
|
|
|
101
170
|
// =============================================================================
|
|
@@ -119,8 +188,10 @@ interface ColumnMeta {
|
|
|
119
188
|
schemaType: string;
|
|
120
189
|
/** Index in the _columnPtrs array */
|
|
121
190
|
columnIndex: number;
|
|
122
|
-
/**
|
|
123
|
-
|
|
191
|
+
/** Schema-level eager storage suppresses null bitmaps by declaration. */
|
|
192
|
+
isSchemaEager: boolean;
|
|
193
|
+
/** Compile-proven eager storage is preallocated but remains nullable. */
|
|
194
|
+
isPreallocated: boolean;
|
|
124
195
|
/** Enum values if schemaType === 'enum' */
|
|
125
196
|
enumValues?: readonly string[];
|
|
126
197
|
}
|
|
@@ -137,39 +208,34 @@ function getFieldEnumValues(value: unknown): readonly string[] | undefined {
|
|
|
137
208
|
return Array.isArray(enumValues) ? enumValues : undefined;
|
|
138
209
|
}
|
|
139
210
|
|
|
140
|
-
function
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
): keyof Pick<WasmAllocator, 'free1B' | 'free4B' | 'free8B'> {
|
|
147
|
-
switch (sizeClass) {
|
|
148
|
-
case '1b':
|
|
149
|
-
return 'free1B';
|
|
150
|
-
case '4b':
|
|
151
|
-
return 'free4B';
|
|
152
|
-
case '8b':
|
|
153
|
-
return 'free8B';
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function isWasmSpanBufferConstructor(value: unknown): value is WasmSpanBufferConstructor {
|
|
211
|
+
function isWasmSpanBufferConstructor<T extends LogSchema = LogSchema>(
|
|
212
|
+
value: unknown,
|
|
213
|
+
schema?: T,
|
|
214
|
+
messageLayoutFamily?: MessageLayoutFamily,
|
|
215
|
+
messagePhysicalLayout?: MessagePhysicalLayout,
|
|
216
|
+
): value is WasmSpanBufferConstructor<T> {
|
|
158
217
|
return (
|
|
159
218
|
typeof value === 'function' &&
|
|
160
219
|
typeof Reflect.get(value, 'schema') === 'object' &&
|
|
161
220
|
Reflect.get(value, 'schema') !== null &&
|
|
221
|
+
(schema === undefined || Reflect.get(value, 'schema') === schema) &&
|
|
222
|
+
(messageLayoutFamily === undefined || Reflect.get(value, 'messageLayoutFamily') === messageLayoutFamily) &&
|
|
223
|
+
(messagePhysicalLayout === undefined || Reflect.get(value, 'messagePhysicalLayout') === messagePhysicalLayout) &&
|
|
162
224
|
typeof Reflect.get(value, 'stats') === 'object' &&
|
|
163
225
|
Reflect.get(value, 'stats') !== null
|
|
164
226
|
);
|
|
165
227
|
}
|
|
166
228
|
|
|
167
|
-
export function isWasmSpanBufferInstance
|
|
229
|
+
export function isWasmSpanBufferInstance<T extends LogSchema = LogSchema>(
|
|
230
|
+
value: unknown,
|
|
231
|
+
): value is WasmSpanBufferInstance<T> {
|
|
168
232
|
return typeof value === 'object' && value !== null && typeof Reflect.get(value, '_systemPtr') === 'number';
|
|
169
233
|
}
|
|
170
234
|
|
|
171
|
-
function getWasmSpanBufferConstructor
|
|
172
|
-
|
|
235
|
+
function getWasmSpanBufferConstructor<T extends LogSchema>(
|
|
236
|
+
instance: WasmSpanBufferInstance<T>,
|
|
237
|
+
): WasmSpanBufferConstructor<T> {
|
|
238
|
+
if (!isWasmSpanBufferConstructor(instance.constructor, instance._logSchema)) {
|
|
173
239
|
throw new Error('Expected generated WasmSpanBuffer constructor');
|
|
174
240
|
}
|
|
175
241
|
return instance.constructor;
|
|
@@ -183,15 +249,16 @@ function isWasmSpanBufferFactory(value: unknown): value is () => WasmSpanBufferC
|
|
|
183
249
|
* Build column metadata array from schema.
|
|
184
250
|
* Maps each schema field to its storage characteristics.
|
|
185
251
|
*/
|
|
186
|
-
function buildColumnMeta(schema: LogSchema): ColumnMeta[] {
|
|
252
|
+
function buildColumnMeta(schema: LogSchema, eagerColumns: EagerColumnDescriptor): ColumnMeta[] {
|
|
187
253
|
const result: ColumnMeta[] = [];
|
|
188
254
|
const fields = schema.fields;
|
|
255
|
+
const preallocatedColumns = new Set(eagerColumns.names);
|
|
189
256
|
let columnIndex = 0;
|
|
190
257
|
|
|
191
258
|
for (const name of schema._columnNames) {
|
|
192
259
|
const field = fields[name];
|
|
193
260
|
const schemaType = getSchemaType(field);
|
|
194
|
-
const
|
|
261
|
+
const isSchemaEager = getFieldEager(field);
|
|
195
262
|
const enumValues = getFieldEnumValues(field);
|
|
196
263
|
|
|
197
264
|
let sizeClass: SizeClass;
|
|
@@ -217,7 +284,8 @@ function buildColumnMeta(schema: LogSchema): ColumnMeta[] {
|
|
|
217
284
|
sizeClass,
|
|
218
285
|
schemaType: schemaType ?? 'unknown',
|
|
219
286
|
columnIndex,
|
|
220
|
-
|
|
287
|
+
isSchemaEager,
|
|
288
|
+
isPreallocated: !isSchemaEager && preallocatedColumns.has(name),
|
|
221
289
|
enumValues,
|
|
222
290
|
});
|
|
223
291
|
columnIndex++;
|
|
@@ -230,48 +298,48 @@ function buildColumnMeta(schema: LogSchema): ColumnMeta[] {
|
|
|
230
298
|
// Common WasmSpanBuffer Methods (shared via prototype)
|
|
231
299
|
// =============================================================================
|
|
232
300
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
301
|
+
function wasmEnsureViews(this: WasmSpanBufferInstance): void {
|
|
302
|
+
assertWasmBufferLive(this);
|
|
303
|
+
const memoryVersion = this._allocator.refreshViews();
|
|
304
|
+
if (memoryVersion !== this._viewVersion) this._refreshViews(memoryVersion);
|
|
305
|
+
}
|
|
306
|
+
|
|
237
307
|
function wasmGetTimestamp(this: WasmSpanBufferInstance): BigInt64Array {
|
|
238
|
-
|
|
308
|
+
wasmEnsureViews.call(this);
|
|
309
|
+
return this._timestampView;
|
|
239
310
|
}
|
|
240
311
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
312
|
+
function wasmGetEntryType(this: WasmUnpackedMessageBuffer): Uint8Array {
|
|
313
|
+
wasmEnsureViews.call(this);
|
|
314
|
+
return this._entryTypeView;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function assertWasmBufferLive(buffer: WasmSpanBufferInstance): void {
|
|
318
|
+
if (buffer._descriptor.state !== 'live') {
|
|
319
|
+
const generation = buffer._descriptor.generation;
|
|
320
|
+
throw new Error(
|
|
321
|
+
`Cannot access released WASM buffer generation ${generation}; generation ${generation} has been released`,
|
|
322
|
+
);
|
|
323
|
+
}
|
|
247
324
|
}
|
|
248
325
|
|
|
249
|
-
/**
|
|
250
|
-
* Get writeIndex from WASM identity block.
|
|
251
|
-
*/
|
|
252
326
|
function wasmGetWriteIndex(this: WasmSpanBufferInstance): number {
|
|
253
|
-
|
|
327
|
+
wasmEnsureViews.call(this);
|
|
328
|
+
return this._identityOwner ? this._identityData.getUint32(0, true) : this._overflowWriteIndex;
|
|
254
329
|
}
|
|
255
330
|
|
|
256
|
-
/**
|
|
257
|
-
* Set writeIndex in WASM identity block.
|
|
258
|
-
*/
|
|
259
331
|
function wasmSetWriteIndex(this: WasmSpanBufferInstance, value: number): void {
|
|
260
|
-
|
|
332
|
+
wasmEnsureViews.call(this);
|
|
333
|
+
if (this._identityOwner) {
|
|
334
|
+
this._identityData.setUint32(0, value, true);
|
|
335
|
+
} else {
|
|
336
|
+
this._overflowWriteIndex = value;
|
|
337
|
+
}
|
|
261
338
|
}
|
|
262
339
|
|
|
263
|
-
/**
|
|
264
|
-
* Get trace_id from WASM identity block.
|
|
265
|
-
*/
|
|
266
340
|
function wasmGetTraceId(this: WasmSpanBufferInstance): string {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
let p = this._parent;
|
|
270
|
-
while (p?._parent) p = p._parent;
|
|
271
|
-
return p ? p.trace_id : '';
|
|
272
|
-
}
|
|
273
|
-
const traceIdPtr = this._allocator.getIdentityTraceIdPtr(this._identityPtr);
|
|
274
|
-
return new TextDecoder().decode(new Uint8Array(this._allocator.memory.buffer, traceIdPtr, len));
|
|
341
|
+
assertWasmBufferLive(this);
|
|
342
|
+
return this._traceRoot.trace_id;
|
|
275
343
|
}
|
|
276
344
|
|
|
277
345
|
function wasmGetSpanStartTime(this: WasmSpanBufferInstance): bigint {
|
|
@@ -303,16 +371,13 @@ function wasmGetLastLoggedTime(this: WasmSpanBufferInstance): bigint | null {
|
|
|
303
371
|
* Get thread_id from WASM identity block.
|
|
304
372
|
*/
|
|
305
373
|
function wasmGetThreadId(this: WasmSpanBufferInstance): bigint {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
return (BigInt(high) << 32n) | BigInt(low);
|
|
374
|
+
assertWasmBufferLive(this);
|
|
375
|
+
return this._threadId;
|
|
309
376
|
}
|
|
310
377
|
|
|
311
|
-
/**
|
|
312
|
-
* Get span_id from WASM identity block.
|
|
313
|
-
*/
|
|
314
378
|
function wasmGetSpanId(this: WasmSpanBufferInstance): number {
|
|
315
|
-
|
|
379
|
+
assertWasmBufferLive(this);
|
|
380
|
+
return this._spanId;
|
|
316
381
|
}
|
|
317
382
|
|
|
318
383
|
/**
|
|
@@ -336,102 +401,106 @@ function wasmGetHasParent(this: WasmSpanBufferInstance): boolean {
|
|
|
336
401
|
return this._parent !== null;
|
|
337
402
|
}
|
|
338
403
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
*/
|
|
342
|
-
function wasmMessage(this: WasmSpanBufferInstance, idx: number, value: string): WasmSpanBufferInstance {
|
|
404
|
+
function wasmRawMessage(this: WasmRawMessageBuffer, idx: number, value: string): WasmRawMessageBuffer {
|
|
405
|
+
assertWasmBufferLive(this);
|
|
343
406
|
this._message[idx] = value;
|
|
344
407
|
return this;
|
|
345
408
|
}
|
|
346
409
|
|
|
410
|
+
function wasmStaticMessage(this: WasmSpanBufferInstance, idx: number, value: string): WasmSpanBufferInstance {
|
|
411
|
+
assertWasmBufferLive(this);
|
|
412
|
+
if (idx === 0) this._spanName = value;
|
|
413
|
+
else if (idx === 1) this._terminalMessage = value;
|
|
414
|
+
else throw new RangeError('Static-only buffers only accept raw system messages at rows 0 and 1');
|
|
415
|
+
return this;
|
|
416
|
+
}
|
|
417
|
+
|
|
347
418
|
/**
|
|
348
419
|
* Get message column values.
|
|
349
420
|
*/
|
|
350
|
-
function wasmGetMessageValues(this:
|
|
421
|
+
function wasmGetMessageValues(this: WasmRawMessageBuffer): string[] {
|
|
422
|
+
assertWasmBufferLive(this);
|
|
351
423
|
return this._message;
|
|
352
424
|
}
|
|
353
425
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
*/
|
|
357
|
-
function wasmGetMessageNulls(this: WasmSpanBufferInstance): undefined {
|
|
358
|
-
return undefined;
|
|
426
|
+
function wasmGetMessageLayoutFamily(this: WasmSpanBufferInstance): MessageLayoutFamily {
|
|
427
|
+
return getWasmSpanBufferConstructor(this).messageLayoutFamily;
|
|
359
428
|
}
|
|
360
429
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
function wasmFree(this: WasmSpanBufferInstance): void {
|
|
365
|
-
// Free identity block
|
|
366
|
-
this._allocator.freeIdentity(this._identityPtr);
|
|
430
|
+
function wasmGetMessagePhysicalLayout(this: WasmSpanBufferInstance): MessagePhysicalLayout {
|
|
431
|
+
return getWasmSpanBufferConstructor(this).messagePhysicalLayout;
|
|
432
|
+
}
|
|
367
433
|
|
|
368
|
-
|
|
369
|
-
|
|
434
|
+
/** Free the one owned root/child/overflow superblock exactly once. */
|
|
435
|
+
function wasmFree(this: WasmSpanBufferInstance): void {
|
|
436
|
+
if (this._descriptor.state === 'freed') return;
|
|
437
|
+
if (this._viewVersion !== 0) this._sealStats();
|
|
370
438
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
for (const col of columnMeta) {
|
|
374
|
-
if (col.sizeClass !== 'string' && this._columnPtrs[col.columnIndex] >= 0) {
|
|
375
|
-
const freeMethod = getFreeMethod(col.sizeClass);
|
|
376
|
-
this._allocator[freeMethod](this._columnPtrs[col.columnIndex]);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
439
|
+
this._allocator.freeSpanSuperblock(this._allocationPtr, this._allocationByteLength);
|
|
440
|
+
this._descriptor.state = 'freed';
|
|
379
441
|
}
|
|
380
442
|
|
|
381
443
|
/**
|
|
382
444
|
* Check if column is allocated.
|
|
383
445
|
*/
|
|
384
446
|
function wasmIsColumnAllocated(this: WasmSpanBufferInstance, columnIndex: number): boolean {
|
|
385
|
-
|
|
447
|
+
assertWasmBufferLive(this);
|
|
448
|
+
wasmEnsureViews.call(this);
|
|
449
|
+
return this._columnPtrs[columnIndex] >= 0 || this._getWasmColumnValue(columnIndex) !== undefined;
|
|
386
450
|
}
|
|
387
451
|
|
|
388
|
-
/**
|
|
389
|
-
* Get column values if allocated.
|
|
390
|
-
*/
|
|
452
|
+
/** Get a canonical column value view or JS sidecar without accessor reflection. */
|
|
391
453
|
function wasmGetColumnIfAllocated(this: WasmSpanBufferInstance, columnName: string): ColumnValueType | undefined {
|
|
454
|
+
assertWasmBufferLive(this);
|
|
392
455
|
const idx = this._logSchema._columnNames.indexOf(columnName);
|
|
393
456
|
if (idx === -1) return undefined;
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const value = getter.get.call(this);
|
|
397
|
-
return isColumnValueType(value) ? value : undefined;
|
|
398
|
-
}
|
|
399
|
-
return undefined;
|
|
457
|
+
wasmEnsureViews.call(this);
|
|
458
|
+
return this._getWasmColumnValue(idx);
|
|
400
459
|
}
|
|
401
460
|
|
|
402
|
-
/**
|
|
403
|
-
* Get column nulls if allocated.
|
|
404
|
-
*/
|
|
461
|
+
/** Get a canonical column null-bitmap view without accessor reflection. */
|
|
405
462
|
function wasmGetNullsIfAllocated(this: WasmSpanBufferInstance, columnName: string): Uint8Array | undefined {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
return
|
|
463
|
+
assertWasmBufferLive(this);
|
|
464
|
+
const idx = this._logSchema._columnNames.indexOf(columnName);
|
|
465
|
+
if (idx === -1) return undefined;
|
|
466
|
+
wasmEnsureViews.call(this);
|
|
467
|
+
return this._getWasmColumnNulls(idx);
|
|
411
468
|
}
|
|
412
469
|
|
|
413
|
-
/**
|
|
414
|
-
* Get system ArrayBuffer for compatibility with AnySpanBuffer.
|
|
415
|
-
* WASM uses shared memory, so this returns the entire WASM memory buffer.
|
|
416
|
-
*/
|
|
470
|
+
/** Get the current WASM memory backing store. */
|
|
417
471
|
function wasmGetSystem(this: WasmSpanBufferInstance): ArrayBuffer {
|
|
472
|
+
wasmEnsureViews.call(this);
|
|
418
473
|
return this._allocator.memory.buffer;
|
|
419
474
|
}
|
|
420
475
|
|
|
421
|
-
/**
|
|
422
|
-
* Get identity Uint8Array for compatibility with AnySpanBuffer.
|
|
423
|
-
* Returns a view of the identity block (48 bytes) in WASM memory.
|
|
424
|
-
*/
|
|
476
|
+
/** Get the canonical identity view for the current memory version. */
|
|
425
477
|
function wasmGetIdentity(this: WasmSpanBufferInstance): Uint8Array {
|
|
426
|
-
|
|
427
|
-
return
|
|
478
|
+
wasmEnsureViews.call(this);
|
|
479
|
+
return this._identityView;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function wasmSealStats(this: WasmSpanBufferInstance): void {
|
|
483
|
+
if (this._statsSealed) return;
|
|
484
|
+
const completedRows = this._writeIndex - this._statsReservedRows;
|
|
485
|
+
if (completedRows > 0) getWasmSpanBufferConstructor(this).stats.totalWrites += completedRows;
|
|
486
|
+
this._statsSealed = true;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function wasmSealStatsChain(this: WasmSpanBufferInstance): void {
|
|
490
|
+
let current: WasmSpanBufferInstance | undefined = this;
|
|
491
|
+
while (current) {
|
|
492
|
+
current._sealStats();
|
|
493
|
+
current = current._overflow;
|
|
494
|
+
}
|
|
428
495
|
}
|
|
429
496
|
|
|
430
497
|
/**
|
|
431
498
|
* Get or create overflow buffer.
|
|
432
499
|
*/
|
|
433
500
|
function wasmGetOrCreateOverflow(this: WasmSpanBufferInstance): WasmSpanBufferInstance {
|
|
501
|
+
assertWasmBufferLive(this);
|
|
434
502
|
if (this._overflow) return this._overflow;
|
|
503
|
+
this._sealStats();
|
|
435
504
|
const tracer = this._traceRoot.tracer;
|
|
436
505
|
tracer.onStatsWillResetFor(this);
|
|
437
506
|
checkCapacityTuning(getWasmSpanBufferConstructor(this).stats);
|
|
@@ -472,69 +541,24 @@ function wasmInspect(this: WasmSpanBufferInstance): string {
|
|
|
472
541
|
* Generate eager column initialization code for constructor.
|
|
473
542
|
* Eager columns are pre-allocated, lazy columns start as undefined/-1.
|
|
474
543
|
*/
|
|
475
|
-
function
|
|
544
|
+
function generateColumnInit(columnMeta: ColumnMeta[]): string {
|
|
476
545
|
const lines: string[] = [];
|
|
477
|
-
|
|
478
546
|
for (const col of columnMeta) {
|
|
479
|
-
if (col.name === 'message'
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}
|
|
488
|
-
} else if (col.isEager) {
|
|
489
|
-
lines.push(`this._columnPtrs[${col.columnIndex}] = this._allocator.alloc${col.sizeClass.toUpperCase()}();`);
|
|
547
|
+
if (col.name === 'message' || col.sizeClass !== 'string') continue;
|
|
548
|
+
if (col.isSchemaEager) {
|
|
549
|
+
lines.push(`this._${col.name}_values = new Array(this._capacity);`);
|
|
550
|
+
} else if (col.isPreallocated) {
|
|
551
|
+
lines.push(`this._${col.name}_values = new Array(this._capacity);`);
|
|
552
|
+
lines.push(`this._${col.name}_nulls = new Uint8Array((this._capacity + 7) >>> 3);`);
|
|
553
|
+
} else {
|
|
554
|
+
lines.push(`this._${col.name}_values = undefined;`);
|
|
555
|
+
lines.push(`this._${col.name}_nulls = undefined;`);
|
|
490
556
|
}
|
|
491
557
|
}
|
|
492
|
-
|
|
493
558
|
return lines.join('\n ');
|
|
494
559
|
}
|
|
495
560
|
|
|
496
|
-
|
|
497
|
-
* Generate setter method for a numeric column (stored in WASM).
|
|
498
|
-
* Calls WASM exports directly for hot path optimization.
|
|
499
|
-
*/
|
|
500
|
-
function generateNumericSetter(col: ColumnMeta): string {
|
|
501
|
-
const allocMethod = `alloc${col.sizeClass.toUpperCase()}`;
|
|
502
|
-
|
|
503
|
-
// Map to WASM export names
|
|
504
|
-
const writeExportName =
|
|
505
|
-
col.schemaType === 'number' || col.schemaType === 'bigUint64'
|
|
506
|
-
? 'write_col_f64'
|
|
507
|
-
: col.sizeClass === '1b'
|
|
508
|
-
? 'write_col_u8'
|
|
509
|
-
: col.sizeClass === '4b'
|
|
510
|
-
? 'write_col_u32'
|
|
511
|
-
: 'write_col_f64';
|
|
512
|
-
|
|
513
|
-
if (col.isEager) {
|
|
514
|
-
// Eager: column is pre-allocated, just write value (call WASM export directly)
|
|
515
|
-
return `${col.name}(idx, value) {
|
|
516
|
-
const ptr = this._columnPtrs[${col.columnIndex}];
|
|
517
|
-
this._allocator.exports.${writeExportName}(ptr, idx, value, this._capacity);
|
|
518
|
-
return this;
|
|
519
|
-
}`;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// Lazy: allocate on first write (call WASM export directly)
|
|
523
|
-
return `${col.name}(idx, value) {
|
|
524
|
-
let ptr = this._columnPtrs[${col.columnIndex}];
|
|
525
|
-
if (ptr < 0) {
|
|
526
|
-
ptr = this._allocator.${allocMethod}();
|
|
527
|
-
this._columnPtrs[${col.columnIndex}] = ptr;
|
|
528
|
-
}
|
|
529
|
-
this._allocator.exports.${writeExportName}(ptr, idx, value, this._capacity);
|
|
530
|
-
return this;
|
|
531
|
-
}`;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
* Generate getter for numeric column values (creates view on demand).
|
|
536
|
-
*/
|
|
537
|
-
function generateNumericValuesGetter(col: ColumnMeta): string {
|
|
561
|
+
function generateNumericViewBinding(col: ColumnMeta, layoutIndex: number): string {
|
|
538
562
|
const arrayType =
|
|
539
563
|
col.schemaType === 'number'
|
|
540
564
|
? 'Float64Array'
|
|
@@ -545,65 +569,160 @@ function generateNumericValuesGetter(col: ColumnMeta): string {
|
|
|
545
569
|
: col.sizeClass === '4b'
|
|
546
570
|
? 'Uint32Array'
|
|
547
571
|
: 'Float64Array';
|
|
572
|
+
return `const column = this._layout.columns[${layoutIndex}];
|
|
573
|
+
const familyPtr = this._familyPtrs[column.family];
|
|
574
|
+
this._${col.name}_nulls = new Uint8Array(memory, familyPtr + column.nullOffset, column.nullByteLength);
|
|
575
|
+
this._${col.name}_values = new ${arrayType}(memory, familyPtr + column.valueOffset, this._capacity);
|
|
576
|
+
this._columnPtrs[${col.columnIndex}] = familyPtr + column.nullOffset;`;
|
|
577
|
+
}
|
|
548
578
|
|
|
549
|
-
|
|
579
|
+
function generateEnsureNumericView(col: ColumnMeta, layoutIndex: number): string {
|
|
580
|
+
if (col.isSchemaEager || col.isPreallocated) return '';
|
|
581
|
+
return `if (this._columnPtrs[${col.columnIndex}] === -1) {
|
|
582
|
+
const memory = this._allocator.memory.buffer;
|
|
583
|
+
${generateNumericViewBinding(col, layoutIndex)}
|
|
584
|
+
}`;
|
|
585
|
+
}
|
|
550
586
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
this.
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
);
|
|
587
|
+
function generateNumericSetter(col: ColumnMeta, layoutIndex: number): string {
|
|
588
|
+
const ensureView = generateEnsureNumericView(col, layoutIndex);
|
|
589
|
+
const validity = col.isSchemaEager
|
|
590
|
+
? `this._${col.name}_values[idx] = value;`
|
|
591
|
+
: `if (value == null) {
|
|
592
|
+
this._${col.name}_nulls[idx >>> 3] &= ~(1 << (idx & 7));
|
|
593
|
+
} else {
|
|
594
|
+
this._${col.name}_nulls[idx >>> 3] |= 1 << (idx & 7);
|
|
595
|
+
this._${col.name}_values[idx] = value;
|
|
596
|
+
}`;
|
|
597
|
+
return `${col.name}(idx, value) {
|
|
598
|
+
this._ensureWasmViews();
|
|
599
|
+
${ensureView}
|
|
600
|
+
${validity}
|
|
601
|
+
return this;
|
|
563
602
|
}`;
|
|
564
603
|
}
|
|
565
604
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
// Eager columns don't have null bitmaps
|
|
572
|
-
return `get ${col.name}_nulls() {
|
|
573
|
-
return undefined;
|
|
605
|
+
function generateNumericValuesGetter(col: ColumnMeta, layoutIndex: number): string {
|
|
606
|
+
return `get ${col.name}_values() {
|
|
607
|
+
this._ensureWasmViews();
|
|
608
|
+
${generateEnsureNumericView(col, layoutIndex)}
|
|
609
|
+
return this._${col.name}_values;
|
|
574
610
|
}`;
|
|
575
|
-
|
|
611
|
+
}
|
|
576
612
|
|
|
613
|
+
function generateNumericNullsGetter(col: ColumnMeta, layoutIndex: number): string {
|
|
614
|
+
if (col.isSchemaEager) {
|
|
615
|
+
return `get ${col.name}_nulls() { return undefined; }`;
|
|
616
|
+
}
|
|
577
617
|
return `get ${col.name}_nulls() {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
return new Uint8Array(
|
|
582
|
-
this._allocator.memory.buffer,
|
|
583
|
-
ptr,
|
|
584
|
-
nullBitmapSize
|
|
585
|
-
);
|
|
618
|
+
this._ensureWasmViews();
|
|
619
|
+
${generateEnsureNumericView(col, layoutIndex)}
|
|
620
|
+
return this._${col.name}_nulls;
|
|
586
621
|
}`;
|
|
587
622
|
}
|
|
588
623
|
|
|
624
|
+
function generateViewRefresh(
|
|
625
|
+
columnMeta: ColumnMeta[],
|
|
626
|
+
messageLayoutFamily: MessageLayoutFamily,
|
|
627
|
+
messagePhysicalLayout: MessagePhysicalLayout,
|
|
628
|
+
): string {
|
|
629
|
+
const lines = [
|
|
630
|
+
'const memory = this._allocator.memory.buffer;',
|
|
631
|
+
'this._timestampView = new BigInt64Array(memory, this._systemPtr, this._capacity);',
|
|
632
|
+
];
|
|
633
|
+
if (messagePhysicalLayout === 'packed') {
|
|
634
|
+
lines.push(
|
|
635
|
+
'this._rowHeaders = new Uint32Array(memory, this._systemPtr + this._layout.system.rowHeaderOffset, this._capacity);',
|
|
636
|
+
);
|
|
637
|
+
} else {
|
|
638
|
+
lines.push(
|
|
639
|
+
'this._entryTypeView = new Uint8Array(memory, this._systemPtr + this._layout.system.entryTypeOffset, this._capacity);',
|
|
640
|
+
);
|
|
641
|
+
if (messageLayoutFamily !== 'dynamic-only') {
|
|
642
|
+
if (messagePhysicalLayout === 'current') {
|
|
643
|
+
lines.push(
|
|
644
|
+
'this._messageIds = new Uint16Array(memory, this._systemPtr + this._layout.system.messageIdOffset, this._capacity);',
|
|
645
|
+
);
|
|
646
|
+
} else {
|
|
647
|
+
lines.push(
|
|
648
|
+
'this._logHeaders = new Uint32Array(memory, this._systemPtr + this._layout.system.messageDenseIndexOffset, this._capacity);',
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
lines.push(`if (this._identityOwner) {
|
|
654
|
+
this._identityView = new Uint8Array(memory, this._identityPtr, 128);
|
|
655
|
+
this._identityData = new DataView(memory, this._identityPtr, 128);
|
|
656
|
+
} else {
|
|
657
|
+
this._identitySource._ensureWasmViews();
|
|
658
|
+
this._identityView = this._identitySource._identityView;
|
|
659
|
+
this._identityData = this._identitySource._identityData;
|
|
660
|
+
}`);
|
|
661
|
+
let layoutIndex = 0;
|
|
662
|
+
for (const col of columnMeta) {
|
|
663
|
+
if (col.sizeClass === 'string' || col.name === 'message') continue;
|
|
664
|
+
const binding = generateNumericViewBinding(col, layoutIndex);
|
|
665
|
+
if (col.isSchemaEager || col.isPreallocated) {
|
|
666
|
+
lines.push(`{ ${binding} }`);
|
|
667
|
+
} else {
|
|
668
|
+
lines.push(`if (this._columnPtrs[${col.columnIndex}] !== -1) { ${binding} }`);
|
|
669
|
+
}
|
|
670
|
+
layoutIndex++;
|
|
671
|
+
}
|
|
672
|
+
lines.push('this._viewVersion = version;', 'this._descriptor.memoryVersion = version;');
|
|
673
|
+
return lines.join('\n ');
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
function generateColumnLookup(columnMeta: ColumnMeta[], nulls: boolean): string {
|
|
677
|
+
const cases: string[] = [];
|
|
678
|
+
for (const col of columnMeta) {
|
|
679
|
+
if (col.name === 'message') continue;
|
|
680
|
+
if (nulls && col.isSchemaEager) cases.push(`case ${col.columnIndex}: return undefined;`);
|
|
681
|
+
else {
|
|
682
|
+
const property = nulls ? `_${col.name}_nulls` : `_${col.name}_values`;
|
|
683
|
+
cases.push(`case ${col.columnIndex}: return this.${property};`);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return `switch (columnIndex) { ${cases.join(' ')} default: return undefined; }`;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
function generateEnsureStringStorage(col: ColumnMeta): string {
|
|
690
|
+
if (col.isSchemaEager || col.isPreallocated) return '';
|
|
691
|
+
return `if (this._${col.name}_values === undefined) {
|
|
692
|
+
this._${col.name}_values = new Array(this._capacity);
|
|
693
|
+
this._${col.name}_nulls = new Uint8Array((this._capacity + 7) >>> 3);
|
|
694
|
+
}`;
|
|
695
|
+
}
|
|
696
|
+
|
|
589
697
|
/**
|
|
590
698
|
* Generate setter method for a string column (stored in JS).
|
|
591
699
|
*/
|
|
592
700
|
function generateStringSetter(col: ColumnMeta): string {
|
|
593
|
-
|
|
701
|
+
const ensureStorage = generateEnsureStringStorage(col);
|
|
702
|
+
if (col.isSchemaEager) {
|
|
594
703
|
return `${col.name}(idx, value) {
|
|
704
|
+
if (this._descriptor.state !== 'live') throw new Error('Cannot write a released WASM buffer');
|
|
595
705
|
this._${col.name}_values[idx] = value;
|
|
596
706
|
return this;
|
|
597
707
|
}`;
|
|
598
708
|
}
|
|
599
709
|
|
|
710
|
+
if (col.isPreallocated) {
|
|
711
|
+
return `${col.name}(idx, value) {
|
|
712
|
+
if (this._descriptor.state !== 'live') throw new Error('Cannot write a released WASM buffer');
|
|
713
|
+
if (value == null) this._${col.name}_nulls[idx >>> 3] &= ~(1 << (idx & 7));
|
|
714
|
+
else {
|
|
715
|
+
this._${col.name}_values[idx] = value;
|
|
716
|
+
this._${col.name}_nulls[idx >>> 3] |= 1 << (idx & 7);
|
|
717
|
+
}
|
|
718
|
+
return this;
|
|
719
|
+
}`;
|
|
720
|
+
}
|
|
721
|
+
|
|
600
722
|
// Lazy string column: allocate arrays on first write
|
|
601
723
|
return `${col.name}(idx, value) {
|
|
602
|
-
if (this.
|
|
603
|
-
|
|
604
|
-
const nullBitmapSize = Math.ceil(this._capacity / 8);
|
|
605
|
-
this._${col.name}_nulls = new Uint8Array(nullBitmapSize);
|
|
606
|
-
}
|
|
724
|
+
if (this._descriptor.state !== 'live') throw new Error('Cannot write a released WASM buffer');
|
|
725
|
+
${ensureStorage}
|
|
607
726
|
if (value == null) {
|
|
608
727
|
// Clear validity bit
|
|
609
728
|
this._${col.name}_nulls[idx >>> 3] &= ~(1 << (idx & 7));
|
|
@@ -620,13 +739,10 @@ function generateStringSetter(col: ColumnMeta): string {
|
|
|
620
739
|
* Generate getter for string column values.
|
|
621
740
|
*/
|
|
622
741
|
function generateStringValuesGetter(col: ColumnMeta): string {
|
|
623
|
-
|
|
624
|
-
return `get ${col.name}_values() {
|
|
625
|
-
return this._${col.name}_values;
|
|
626
|
-
}`;
|
|
627
|
-
}
|
|
628
|
-
|
|
742
|
+
const ensureStorage = generateEnsureStringStorage(col);
|
|
629
743
|
return `get ${col.name}_values() {
|
|
744
|
+
if (this._descriptor.state !== 'live') throw new Error('Cannot read a released WASM buffer');
|
|
745
|
+
${ensureStorage}
|
|
630
746
|
return this._${col.name}_values;
|
|
631
747
|
}`;
|
|
632
748
|
}
|
|
@@ -635,13 +751,16 @@ function generateStringValuesGetter(col: ColumnMeta): string {
|
|
|
635
751
|
* Generate getter for string column nulls.
|
|
636
752
|
*/
|
|
637
753
|
function generateStringNullsGetter(col: ColumnMeta): string {
|
|
638
|
-
if (col.
|
|
754
|
+
if (col.isSchemaEager) {
|
|
639
755
|
return `get ${col.name}_nulls() {
|
|
640
756
|
return undefined;
|
|
641
757
|
}`;
|
|
642
758
|
}
|
|
643
759
|
|
|
760
|
+
const ensureStorage = generateEnsureStringStorage(col);
|
|
644
761
|
return `get ${col.name}_nulls() {
|
|
762
|
+
if (this._descriptor.state !== 'live') throw new Error('Cannot read a released WASM buffer');
|
|
763
|
+
${ensureStorage}
|
|
645
764
|
return this._${col.name}_nulls;
|
|
646
765
|
}`;
|
|
647
766
|
}
|
|
@@ -652,21 +771,19 @@ function generateStringNullsGetter(col: ColumnMeta): string {
|
|
|
652
771
|
*/
|
|
653
772
|
function generateColumnMethods(columnMeta: ColumnMeta[]): string {
|
|
654
773
|
const methods: string[] = [];
|
|
774
|
+
let layoutIndex = 0;
|
|
655
775
|
|
|
656
776
|
for (const col of columnMeta) {
|
|
657
|
-
|
|
658
|
-
if (col.name === 'message') {
|
|
659
|
-
continue;
|
|
660
|
-
}
|
|
661
|
-
|
|
777
|
+
if (col.name === 'message') continue;
|
|
662
778
|
if (col.sizeClass === 'string') {
|
|
663
779
|
methods.push(generateStringSetter(col));
|
|
664
780
|
methods.push(generateStringValuesGetter(col));
|
|
665
781
|
methods.push(generateStringNullsGetter(col));
|
|
666
782
|
} else {
|
|
667
|
-
methods.push(generateNumericSetter(col));
|
|
668
|
-
methods.push(generateNumericValuesGetter(col));
|
|
669
|
-
methods.push(generateNumericNullsGetter(col));
|
|
783
|
+
methods.push(generateNumericSetter(col, layoutIndex));
|
|
784
|
+
methods.push(generateNumericValuesGetter(col, layoutIndex));
|
|
785
|
+
methods.push(generateNumericNullsGetter(col, layoutIndex));
|
|
786
|
+
layoutIndex++;
|
|
670
787
|
}
|
|
671
788
|
}
|
|
672
789
|
|
|
@@ -677,11 +794,8 @@ function generateColumnMethods(columnMeta: ColumnMeta[]): string {
|
|
|
677
794
|
// Class Cache and Generation
|
|
678
795
|
// =============================================================================
|
|
679
796
|
|
|
680
|
-
/**
|
|
681
|
-
|
|
682
|
-
* Key is the schema object reference (WeakMap for GC).
|
|
683
|
-
*/
|
|
684
|
-
const wasmSpanBufferClassCache = new WeakMap<LogSchema, WasmSpanBufferConstructor>();
|
|
797
|
+
/** Cache for generated WASM SpanBuffer classes, partitioned by schema and message family. */
|
|
798
|
+
const wasmSpanBufferClassCache = new WeakMap<LogSchema, Map<string, object>>();
|
|
685
799
|
|
|
686
800
|
/**
|
|
687
801
|
* Generate a WASM SpanBuffer class for the given schema.
|
|
@@ -691,61 +805,141 @@ const wasmSpanBufferClassCache = new WeakMap<LogSchema, WasmSpanBufferConstructo
|
|
|
691
805
|
* @param schema - LogSchema defining the buffer structure
|
|
692
806
|
* @returns WasmSpanBufferConstructor for creating buffer instances
|
|
693
807
|
*/
|
|
694
|
-
export function getWasmSpanBufferClass
|
|
695
|
-
|
|
696
|
-
|
|
808
|
+
export function getWasmSpanBufferClass<T extends LogSchema>(
|
|
809
|
+
schema: T,
|
|
810
|
+
messageLayoutFamily: MessageLayoutFamily = 'mixed',
|
|
811
|
+
messagePhysicalLayout: MessagePhysicalLayout = 'current',
|
|
812
|
+
eagerColumns: EagerColumnDescriptor = EMPTY_EAGER_COLUMNS,
|
|
813
|
+
): WasmSpanBufferConstructor<T> {
|
|
814
|
+
const cacheKey = `${messageLayoutFamily}:${messagePhysicalLayout}:${eagerColumns.key}`;
|
|
815
|
+
let familyClasses = wasmSpanBufferClassCache.get(schema);
|
|
816
|
+
const cached = familyClasses?.get(cacheKey);
|
|
817
|
+
if (cached !== undefined && isWasmSpanBufferConstructor(cached, schema, messageLayoutFamily, messagePhysicalLayout))
|
|
697
818
|
return cached;
|
|
698
|
-
}
|
|
699
819
|
|
|
700
|
-
|
|
701
|
-
const columnMeta = buildColumnMeta(schema);
|
|
820
|
+
const columnMeta = buildColumnMeta(schema, eagerColumns);
|
|
702
821
|
|
|
703
822
|
// Generate ONLY schema-specific code (constructor + column methods)
|
|
704
823
|
const classCode = `
|
|
705
824
|
class WasmSpanBuffer {
|
|
706
825
|
constructor(opts) {
|
|
707
|
-
// Store allocator and capacity
|
|
708
826
|
this._allocator = opts.allocator;
|
|
709
827
|
this._capacity = opts.capacity;
|
|
710
828
|
this._logSchema = opts.logSchema;
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
const traceIdBytes = new TextEncoder().encode(opts.trace_id);
|
|
715
|
-
const packed = opts.allocator.allocIdentityRootForJsWrite(traceIdBytes.length);
|
|
716
|
-
this._identityPtr = Number(packed >> 32n);
|
|
717
|
-
const traceIdOffset = Number(packed & 0xFFFFFFFFn);
|
|
718
|
-
new Uint8Array(opts.allocator.memory.buffer).set(traceIdBytes, traceIdOffset);
|
|
719
|
-
} else {
|
|
720
|
-
this._identityPtr = opts.allocator.allocIdentityChild();
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// Allocate system block from WASM
|
|
724
|
-
this._systemPtr = opts.allocator.allocSpanSystem();
|
|
725
|
-
|
|
726
|
-
// Initialize column pointers as unallocated (-1)
|
|
727
|
-
this._columnPtrs = new Int32Array(${columnMeta.length}).fill(-1);
|
|
728
|
-
|
|
729
|
-
// Tree structure
|
|
730
|
-
this._parent = null;
|
|
731
|
-
this._children = [];
|
|
829
|
+
this._parent = opts._parent ?? null;
|
|
830
|
+
this._nodeIndex = 4294967295;
|
|
831
|
+
this._topologyGeneration = 0;
|
|
732
832
|
this._overflow = null;
|
|
833
|
+
this._overflowWriteIndex = 0;
|
|
834
|
+
this._layout = opts._layout;
|
|
835
|
+
if (this._layout.messageLayoutFamily !== '${messageLayoutFamily}') {
|
|
836
|
+
throw new TypeError('WASM layout descriptor does not match its generated message family');
|
|
837
|
+
}
|
|
838
|
+
if (this._layout.messagePhysicalLayout !== '${messagePhysicalLayout}') {
|
|
839
|
+
throw new TypeError('WASM layout descriptor does not match its generated physical layout');
|
|
840
|
+
}
|
|
733
841
|
|
|
734
|
-
// Assign context properties from opts
|
|
735
842
|
this._traceRoot = opts._traceRoot;
|
|
736
843
|
this._scopeValues = opts._scopeValues;
|
|
737
844
|
this._opMetadata = opts._opMetadata;
|
|
738
845
|
this._callsiteMetadata = opts._callsiteMetadata;
|
|
846
|
+
this._vocabularyGeneration = opts._vocabularyGeneration;
|
|
847
|
+
this._statsSealed = false;
|
|
848
|
+
this._statsReservedRows = 2;
|
|
849
|
+
this._columnPtrs = new Int32Array(${columnMeta.length}).fill(-1);
|
|
850
|
+
${
|
|
851
|
+
messageLayoutFamily === 'static-only'
|
|
852
|
+
? `this._spanName = undefined;
|
|
853
|
+
this._terminalMessage = undefined;`
|
|
854
|
+
: messageLayoutFamily === 'dynamic-only'
|
|
855
|
+
? `this._spanName = undefined;
|
|
856
|
+
this._message = new Array(opts.capacity);`
|
|
857
|
+
: 'this._message = new Array(opts.capacity);'
|
|
858
|
+
}
|
|
859
|
+
${generateColumnInit(columnMeta)}
|
|
860
|
+
|
|
861
|
+
const identityMode = opts._identityMode ?? 'root';
|
|
862
|
+
this._identityOwner = identityMode !== 'overflow';
|
|
863
|
+
this._identitySource = identityMode === 'overflow' ? opts._identitySource : undefined;
|
|
864
|
+
const superblock = this._identityOwner ? this._layout.spanSuperblock : this._layout.overflowSuperblock;
|
|
865
|
+
this._allocationByteLength = superblock.byteLength;
|
|
866
|
+
if (identityMode === 'overflow') {
|
|
867
|
+
if (!this._identitySource) throw new Error('Overflow buffer requires an identity owner');
|
|
868
|
+
this._allocationPtr = opts.allocator.createOverflowSpan(superblock.byteLength);
|
|
869
|
+
this._identityPtr = this._identitySource._identityPtr;
|
|
870
|
+
} else {
|
|
871
|
+
const traceRootPtr = opts._traceRoot._traceRootPtr;
|
|
872
|
+
if (!Number.isInteger(traceRootPtr) || traceRootPtr <= 0) {
|
|
873
|
+
throw new TypeError('WASM span requires a live WasmTraceRoot');
|
|
874
|
+
}
|
|
875
|
+
const traceIdBytes = identityMode === 'root' ? opts._traceRoot._traceIdBytes : undefined;
|
|
876
|
+
this._allocationPtr = opts.allocator.createAndStartSpan(
|
|
877
|
+
identityMode === 'child' ? ${WASM_SPAN_IDENTITY_CHILD} : ${WASM_SPAN_IDENTITY_ROOT},
|
|
878
|
+
traceIdBytes?.length ?? 0,
|
|
879
|
+
superblock.byteLength,
|
|
880
|
+
superblock.systemOffset,
|
|
881
|
+
this._layout.system.entryTypeOffset ?? ${WASM_NO_LAYOUT_OFFSET},
|
|
882
|
+
this._layout.system.rowHeaderOffset ?? ${WASM_NO_LAYOUT_OFFSET},
|
|
883
|
+
traceRootPtr,
|
|
884
|
+
);
|
|
885
|
+
this._identityPtr = this._allocationPtr;
|
|
886
|
+
if (this._allocationPtr !== 0 && traceIdBytes !== undefined) {
|
|
887
|
+
opts.allocator.u8.set(traceIdBytes, this._identityPtr + 9);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
if (this._allocationPtr === 0) throw new Error('WASM span superblock allocation failed');
|
|
739
891
|
|
|
740
|
-
|
|
741
|
-
|
|
892
|
+
this._systemPtr = this._allocationPtr + superblock.systemOffset;
|
|
893
|
+
const familyPtrs = { u8: 0, u32: 0, f64: 0 };
|
|
894
|
+
for (const family of ['u8', 'u32', 'f64']) {
|
|
895
|
+
const familyOffset = superblock.familyOffsets[family];
|
|
896
|
+
if (familyOffset !== 0) familyPtrs[family] = this._allocationPtr + familyOffset;
|
|
897
|
+
}
|
|
898
|
+
this._familyPtrs = Object.freeze(familyPtrs);
|
|
899
|
+
const allocatorWords = opts.allocator.u32;
|
|
900
|
+
this._threadId =
|
|
901
|
+
this._identitySource?.thread_id ?? ((BigInt(allocatorWords[7]) << 32n) | BigInt(allocatorWords[6]));
|
|
902
|
+
this._spanId = this._identitySource?.span_id ?? allocatorWords[(this._identityPtr + 4) >>> 2];
|
|
903
|
+
this._viewVersion = 0;
|
|
904
|
+
this._spanStartedAtAllocation = this._identityOwner;
|
|
905
|
+
|
|
906
|
+
this._descriptor = {
|
|
907
|
+
generation: opts._generation ?? 0,
|
|
908
|
+
kind: identityMode,
|
|
909
|
+
state: 'live',
|
|
910
|
+
layout: this._layout,
|
|
911
|
+
allocationPtr: this._allocationPtr,
|
|
912
|
+
allocationByteLength: this._allocationByteLength,
|
|
913
|
+
systemPtr: this._systemPtr,
|
|
914
|
+
familyPtrs: this._familyPtrs,
|
|
915
|
+
identityPtr: this._identityPtr,
|
|
916
|
+
ownsIdentity: this._identityOwner,
|
|
917
|
+
memoryVersion: 0,
|
|
918
|
+
parent: opts._parent?._descriptor,
|
|
919
|
+
};
|
|
920
|
+
|
|
921
|
+
try {
|
|
922
|
+
this._refreshViews(this._allocator.refreshViews());
|
|
923
|
+
} catch (error) {
|
|
924
|
+
this.free();
|
|
925
|
+
throw error;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
_refreshViews(version) {
|
|
930
|
+
${generateViewRefresh(columnMeta, messageLayoutFamily, messagePhysicalLayout)}
|
|
931
|
+
}
|
|
742
932
|
|
|
743
|
-
|
|
744
|
-
${
|
|
933
|
+
_getWasmColumnValue(columnIndex) {
|
|
934
|
+
${generateColumnLookup(columnMeta, false)}
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
_getWasmColumnNulls(columnIndex) {
|
|
938
|
+
${generateColumnLookup(columnMeta, true)}
|
|
745
939
|
}
|
|
746
940
|
|
|
747
|
-
// Schema-specific column methods (ONLY part that differs per schema)
|
|
748
941
|
${generateColumnMethods(columnMeta)}
|
|
942
|
+
|
|
749
943
|
}
|
|
750
944
|
|
|
751
945
|
return WasmSpanBuffer;
|
|
@@ -764,11 +958,13 @@ return WasmSpanBuffer;
|
|
|
764
958
|
enumerable: true,
|
|
765
959
|
configurable: true,
|
|
766
960
|
});
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
961
|
+
if (messagePhysicalLayout !== 'packed') {
|
|
962
|
+
Object.defineProperty(WasmSpanBufferClass.prototype, 'entry_type', {
|
|
963
|
+
get: wasmGetEntryType,
|
|
964
|
+
enumerable: true,
|
|
965
|
+
configurable: true,
|
|
966
|
+
});
|
|
967
|
+
}
|
|
772
968
|
Object.defineProperty(WasmSpanBufferClass.prototype, '_writeIndex', {
|
|
773
969
|
get: wasmGetWriteIndex,
|
|
774
970
|
set: wasmSetWriteIndex,
|
|
@@ -805,13 +1001,20 @@ return WasmSpanBuffer;
|
|
|
805
1001
|
enumerable: true,
|
|
806
1002
|
configurable: true,
|
|
807
1003
|
});
|
|
808
|
-
|
|
809
|
-
|
|
1004
|
+
if (messageLayoutFamily !== 'static-only') {
|
|
1005
|
+
Object.defineProperty(WasmSpanBufferClass.prototype, 'message_values', {
|
|
1006
|
+
get: wasmGetMessageValues,
|
|
1007
|
+
enumerable: true,
|
|
1008
|
+
configurable: true,
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
Object.defineProperty(WasmSpanBufferClass.prototype, '_messageLayoutFamily', {
|
|
1012
|
+
get: wasmGetMessageLayoutFamily,
|
|
810
1013
|
enumerable: true,
|
|
811
1014
|
configurable: true,
|
|
812
1015
|
});
|
|
813
|
-
Object.defineProperty(WasmSpanBufferClass.prototype, '
|
|
814
|
-
get:
|
|
1016
|
+
Object.defineProperty(WasmSpanBufferClass.prototype, '_messagePhysicalLayout', {
|
|
1017
|
+
get: wasmGetMessagePhysicalLayout,
|
|
815
1018
|
enumerable: true,
|
|
816
1019
|
configurable: true,
|
|
817
1020
|
});
|
|
@@ -848,12 +1051,15 @@ return WasmSpanBuffer;
|
|
|
848
1051
|
configurable: true,
|
|
849
1052
|
});
|
|
850
1053
|
|
|
851
|
-
WasmSpanBufferClass.prototype.
|
|
1054
|
+
WasmSpanBufferClass.prototype._ensureWasmViews = wasmEnsureViews;
|
|
1055
|
+
WasmSpanBufferClass.prototype.message = messageLayoutFamily === 'static-only' ? wasmStaticMessage : wasmRawMessage;
|
|
852
1056
|
WasmSpanBufferClass.prototype.free = wasmFree;
|
|
853
1057
|
WasmSpanBufferClass.prototype.isColumnAllocated = wasmIsColumnAllocated;
|
|
854
1058
|
WasmSpanBufferClass.prototype.getColumnIfAllocated = wasmGetColumnIfAllocated;
|
|
855
1059
|
WasmSpanBufferClass.prototype.getNullsIfAllocated = wasmGetNullsIfAllocated;
|
|
856
1060
|
WasmSpanBufferClass.prototype.getOrCreateOverflow = wasmGetOrCreateOverflow;
|
|
1061
|
+
WasmSpanBufferClass.prototype._sealStats = wasmSealStats;
|
|
1062
|
+
WasmSpanBufferClass.prototype._sealStatsChain = wasmSealStatsChain;
|
|
857
1063
|
WasmSpanBufferClass.prototype[Symbol.for('nodejs.util.inspect.custom')] = wasmInspect;
|
|
858
1064
|
|
|
859
1065
|
// Add static schema property
|
|
@@ -863,6 +1069,24 @@ return WasmSpanBuffer;
|
|
|
863
1069
|
enumerable: true,
|
|
864
1070
|
configurable: false,
|
|
865
1071
|
});
|
|
1072
|
+
Object.defineProperty(WasmSpanBufferClass, 'messageLayoutFamily', {
|
|
1073
|
+
value: messageLayoutFamily,
|
|
1074
|
+
writable: false,
|
|
1075
|
+
enumerable: true,
|
|
1076
|
+
configurable: false,
|
|
1077
|
+
});
|
|
1078
|
+
Object.defineProperty(WasmSpanBufferClass, 'messagePhysicalLayout', {
|
|
1079
|
+
value: messagePhysicalLayout,
|
|
1080
|
+
writable: false,
|
|
1081
|
+
enumerable: true,
|
|
1082
|
+
configurable: false,
|
|
1083
|
+
});
|
|
1084
|
+
Object.defineProperty(WasmSpanBufferClass, 'eagerColumns', {
|
|
1085
|
+
value: eagerColumns,
|
|
1086
|
+
writable: false,
|
|
1087
|
+
enumerable: true,
|
|
1088
|
+
configurable: false,
|
|
1089
|
+
});
|
|
866
1090
|
|
|
867
1091
|
// Add static stats property (required by SpanContext and arrow-builder's ColumnWriter)
|
|
868
1092
|
// This matches the structure in spanBuffer.ts
|
|
@@ -879,8 +1103,13 @@ return WasmSpanBuffer;
|
|
|
879
1103
|
configurable: true,
|
|
880
1104
|
});
|
|
881
1105
|
|
|
882
|
-
|
|
883
|
-
|
|
1106
|
+
if (!isWasmSpanBufferConstructor(WasmSpanBufferClass, schema)) {
|
|
1107
|
+
throw new Error('Generated WasmSpanBuffer constructor lost its schema identity');
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
familyClasses ??= new Map();
|
|
1111
|
+
familyClasses.set(cacheKey, WasmSpanBufferClass);
|
|
1112
|
+
wasmSpanBufferClassCache.set(schema, familyClasses);
|
|
884
1113
|
|
|
885
1114
|
return WasmSpanBufferClass;
|
|
886
1115
|
}
|
|
@@ -898,24 +1127,40 @@ return WasmSpanBuffer;
|
|
|
898
1127
|
* @param _scopeValues - Scope values for this span
|
|
899
1128
|
* @param _opMetadata - Op metadata for attribution
|
|
900
1129
|
* @param _callsiteMetadata - Callsite metadata for attribution
|
|
901
|
-
* @returns
|
|
1130
|
+
* @returns Schema-specific WASM buffer instance
|
|
902
1131
|
*/
|
|
903
|
-
export function createWasmSpanBuffer(
|
|
904
|
-
schema:
|
|
905
|
-
opts: Omit<
|
|
906
|
-
|
|
1132
|
+
export function createWasmSpanBuffer<T extends LogSchema>(
|
|
1133
|
+
schema: T,
|
|
1134
|
+
opts: Omit<
|
|
1135
|
+
WasmSpanBufferOptions<T>,
|
|
1136
|
+
| 'logSchema'
|
|
1137
|
+
| '_traceRoot'
|
|
1138
|
+
| '_scopeValues'
|
|
1139
|
+
| '_opMetadata'
|
|
1140
|
+
| '_callsiteMetadata'
|
|
1141
|
+
| '_vocabularyGeneration'
|
|
1142
|
+
| '_layout'
|
|
1143
|
+
>,
|
|
1144
|
+
_traceRoot: ITraceRoot<T>,
|
|
907
1145
|
_scopeValues: Readonly<Record<string, unknown>>,
|
|
908
1146
|
_opMetadata: OpMetadata,
|
|
909
1147
|
_callsiteMetadata: OpMetadata,
|
|
910
|
-
): WasmSpanBufferInstance {
|
|
911
|
-
const
|
|
1148
|
+
): WasmSpanBufferInstance<T> {
|
|
1149
|
+
const messageLayoutFamily = opts.messageLayoutFamily ?? 'mixed';
|
|
1150
|
+
const messagePhysicalLayout = opts.messagePhysicalLayout ?? 'current';
|
|
1151
|
+
const eagerColumns = _opMetadata._physicalLayoutPlan?.eagerColumns ?? EMPTY_EAGER_COLUMNS;
|
|
1152
|
+
const WasmSpanBufferClass = getWasmSpanBufferClass(schema, messageLayoutFamily, messagePhysicalLayout, eagerColumns);
|
|
912
1153
|
return new WasmSpanBufferClass({
|
|
913
1154
|
...opts,
|
|
1155
|
+
_identityMode: 'root',
|
|
1156
|
+
_generation: ++nextWasmBufferGeneration,
|
|
1157
|
+
_layout: getWasmPhysicalLayout(schema, opts.capacity, messageLayoutFamily, messagePhysicalLayout, eagerColumns),
|
|
914
1158
|
logSchema: schema,
|
|
915
1159
|
_traceRoot,
|
|
916
1160
|
_scopeValues,
|
|
917
1161
|
_opMetadata,
|
|
918
1162
|
_callsiteMetadata,
|
|
1163
|
+
_vocabularyGeneration: _opMetadata._physicalLayoutPlan?.vocabularyGeneration ?? getVocabularyGeneration(),
|
|
919
1164
|
});
|
|
920
1165
|
}
|
|
921
1166
|
|
|
@@ -931,47 +1176,58 @@ export function createWasmSpanBuffer(
|
|
|
931
1176
|
* @param _scopeValues - Scope values for this span
|
|
932
1177
|
* @param _opMetadata - Op metadata for attribution
|
|
933
1178
|
* @param _callsiteMetadata - Callsite metadata for attribution
|
|
934
|
-
* @returns
|
|
1179
|
+
* @returns Schema-specific child WASM buffer
|
|
935
1180
|
*/
|
|
936
|
-
export function createWasmChildSpanBuffer(
|
|
937
|
-
parent: WasmSpanBufferInstance
|
|
1181
|
+
export function createWasmChildSpanBuffer<T extends LogSchema>(
|
|
1182
|
+
parent: WasmSpanBufferInstance<T>,
|
|
938
1183
|
opts: Omit<
|
|
939
|
-
WasmSpanBufferOptions
|
|
1184
|
+
WasmSpanBufferOptions<T>,
|
|
940
1185
|
| 'logSchema'
|
|
941
|
-
| 'trace_id'
|
|
942
|
-
| 'parent_thread_id'
|
|
943
|
-
| 'parent_span_id'
|
|
944
1186
|
| '_traceRoot'
|
|
945
1187
|
| '_scopeValues'
|
|
946
1188
|
| '_opMetadata'
|
|
947
1189
|
| '_callsiteMetadata'
|
|
1190
|
+
| '_vocabularyGeneration'
|
|
1191
|
+
| '_layout'
|
|
948
1192
|
> & {
|
|
949
|
-
schema?:
|
|
1193
|
+
schema?: T;
|
|
950
1194
|
},
|
|
951
|
-
_traceRoot: ITraceRoot
|
|
1195
|
+
_traceRoot: ITraceRoot<T>,
|
|
952
1196
|
_scopeValues: Readonly<Record<string, unknown>>,
|
|
953
1197
|
_opMetadata: OpMetadata,
|
|
954
1198
|
_callsiteMetadata: OpMetadata,
|
|
955
|
-
): WasmSpanBufferInstance {
|
|
1199
|
+
): WasmSpanBufferInstance<T> {
|
|
956
1200
|
// Use provided schema (for cross-library calls) or parent's schema
|
|
957
1201
|
const childSchema = opts.schema ?? parent._logSchema;
|
|
958
|
-
const
|
|
959
|
-
|
|
1202
|
+
const messageLayoutFamily = opts.messageLayoutFamily ?? parent._messageLayoutFamily;
|
|
1203
|
+
const messagePhysicalLayout = opts.messagePhysicalLayout ?? parent._messagePhysicalLayout;
|
|
1204
|
+
const eagerColumns = _opMetadata._physicalLayoutPlan?.eagerColumns ?? EMPTY_EAGER_COLUMNS;
|
|
1205
|
+
const WasmSpanBufferClass = getWasmSpanBufferClass(
|
|
1206
|
+
childSchema,
|
|
1207
|
+
messageLayoutFamily,
|
|
1208
|
+
messagePhysicalLayout,
|
|
1209
|
+
eagerColumns,
|
|
1210
|
+
);
|
|
960
1211
|
const child = new WasmSpanBufferClass({
|
|
961
1212
|
...opts,
|
|
962
|
-
logSchema: childSchema,
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1213
|
+
logSchema: childSchema,
|
|
1214
|
+
_identityMode: 'child',
|
|
1215
|
+
_parent: parent,
|
|
1216
|
+
_generation: ++nextWasmBufferGeneration,
|
|
1217
|
+
_layout: getWasmPhysicalLayout(
|
|
1218
|
+
childSchema,
|
|
1219
|
+
opts.capacity,
|
|
1220
|
+
messageLayoutFamily,
|
|
1221
|
+
messagePhysicalLayout,
|
|
1222
|
+
eagerColumns,
|
|
1223
|
+
),
|
|
966
1224
|
_traceRoot,
|
|
967
1225
|
_scopeValues,
|
|
968
1226
|
_opMetadata,
|
|
969
1227
|
_callsiteMetadata,
|
|
1228
|
+
_vocabularyGeneration: _opMetadata._physicalLayoutPlan?.vocabularyGeneration ?? getVocabularyGeneration(),
|
|
970
1229
|
});
|
|
971
1230
|
|
|
972
|
-
// Link to parent (SpanContext will push to parent._children with possible RemappedBufferView wrapper)
|
|
973
|
-
child._parent = parent;
|
|
974
|
-
|
|
975
1231
|
return child;
|
|
976
1232
|
}
|
|
977
1233
|
|
|
@@ -983,35 +1239,35 @@ export function createWasmChildSpanBuffer(
|
|
|
983
1239
|
* @param _scopeValues - Scope values for this span
|
|
984
1240
|
* @param _opMetadata - Op metadata for attribution
|
|
985
1241
|
* @param _callsiteMetadata - Callsite metadata for attribution
|
|
986
|
-
* @returns
|
|
1242
|
+
* @returns Schema-specific overflow WASM buffer
|
|
987
1243
|
*/
|
|
988
|
-
export function createWasmOverflowBuffer(
|
|
989
|
-
buffer: WasmSpanBufferInstance
|
|
990
|
-
_traceRoot: ITraceRoot
|
|
1244
|
+
export function createWasmOverflowBuffer<T extends LogSchema>(
|
|
1245
|
+
buffer: WasmSpanBufferInstance<T>,
|
|
1246
|
+
_traceRoot: ITraceRoot<T>,
|
|
991
1247
|
_scopeValues: Readonly<Record<string, unknown>>,
|
|
992
1248
|
_opMetadata: OpMetadata,
|
|
993
1249
|
_callsiteMetadata: OpMetadata,
|
|
994
|
-
): WasmSpanBufferInstance {
|
|
995
|
-
const WasmSpanBufferClass =
|
|
1250
|
+
): WasmSpanBufferInstance<T> {
|
|
1251
|
+
const WasmSpanBufferClass = getWasmSpanBufferConstructor(buffer);
|
|
996
1252
|
|
|
997
1253
|
const overflow = new WasmSpanBufferClass({
|
|
998
1254
|
allocator: buffer._allocator,
|
|
999
1255
|
capacity: buffer._capacity,
|
|
1000
|
-
trace_id: buffer.trace_id,
|
|
1001
|
-
thread_id: buffer.thread_id,
|
|
1002
|
-
span_id: buffer.span_id,
|
|
1003
|
-
parent_thread_id: buffer.parent_thread_id,
|
|
1004
|
-
parent_span_id: buffer.parent_span_id,
|
|
1005
1256
|
logSchema: buffer._logSchema,
|
|
1006
1257
|
_traceRoot,
|
|
1007
1258
|
_scopeValues,
|
|
1008
1259
|
_opMetadata,
|
|
1009
1260
|
_callsiteMetadata,
|
|
1261
|
+
_vocabularyGeneration: buffer._vocabularyGeneration,
|
|
1262
|
+
_identityMode: 'overflow',
|
|
1263
|
+
_identitySource: buffer._identitySource ?? buffer,
|
|
1264
|
+
_parent: buffer._parent,
|
|
1265
|
+
_generation: ++nextWasmBufferGeneration,
|
|
1266
|
+
_layout: buffer._layout,
|
|
1010
1267
|
});
|
|
1011
|
-
|
|
1012
|
-
// Link as overflow (not child - same logical span)
|
|
1013
|
-
overflow._parent = buffer._parent;
|
|
1268
|
+
overflow._statsReservedRows = 0;
|
|
1014
1269
|
buffer._overflow = overflow;
|
|
1270
|
+
buffer._descriptor.overflow = overflow._descriptor;
|
|
1015
1271
|
|
|
1016
1272
|
return overflow;
|
|
1017
1273
|
}
|