Skip to content

Commit 2c02ef4

Browse files
committed
perf(dash-wasm): share empty child arrays
1 parent 2717573 commit 2c02ef4

5 files changed

Lines changed: 68 additions & 44 deletions

File tree

‎src/parsers/manifest/dash/wasm-parser/ts/generators/AdaptationSet.ts‎

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import noop from "../../../../../../utils/noop.ts";
1818
import type {
1919
IAdaptationSetAttributes,
2020
IAdaptationSetChildren,
21+
IRepresentationIntermediateRepresentation,
2122
ISegmentListIntermediateRepresentation,
2223
} from "../../../node_parser_types.ts";
2324
import type { IAttributeParser, IChildrenParser } from "../parsers_stack.ts";
@@ -28,6 +29,7 @@ import { generateBaseUrlAttrParser } from "./BaseURL.ts";
2829
import { generateContentComponentAttrParser } from "./ContentComponent.ts";
2930
import { generateContentProtectionAttrParser } from "./ContentProtection.ts";
3031
import { generateLabelElementParser } from "./Label.ts";
32+
import { emptyChildArray, pushChild } from "./lazy_child_array.ts";
3133
import {
3234
generateRepresentationAttrParser,
3335
generateRepresentationChildrenParser,
@@ -59,7 +61,7 @@ export function generateAdaptationSetChildrenParser(
5961
switch (nodeId) {
6062
case TagName.Accessibility: {
6163
const accessibility = { attributes: {} };
62-
adaptationSetChildren.Accessibility.push(accessibility);
64+
pushChild(adaptationSetChildren, "Accessibility", accessibility);
6365
const schemeAttrParser = generateSchemeAttrParser(
6466
accessibility.attributes,
6567
linearMemory,
@@ -70,15 +72,15 @@ export function generateAdaptationSetChildrenParser(
7072

7173
case TagName.BaseURL: {
7274
const baseUrl = { value: "", attributes: {} };
73-
adaptationSetChildren.BaseURL.push(baseUrl);
75+
pushChild(adaptationSetChildren, "BaseURL", baseUrl);
7476
const attributeParser = generateBaseUrlAttrParser(baseUrl, linearMemory);
7577
parsersStack.pushParsers(nodeId, noop, attributeParser);
7678
break;
7779
}
7880

7981
case TagName.ContentComponent: {
8082
const contentComponent = { attributes: {} };
81-
adaptationSetChildren.ContentComponent.push(contentComponent);
83+
pushChild(adaptationSetChildren, "ContentComponent", contentComponent);
8284
parsersStack.pushParsers(
8385
nodeId,
8486
noop,
@@ -92,7 +94,7 @@ export function generateAdaptationSetChildrenParser(
9294
children: { ["cenc:pssh"]: [] },
9395
attributes: {},
9496
};
95-
adaptationSetChildren.ContentProtection.push(contentProtection);
97+
pushChild(adaptationSetChildren, "ContentProtection", contentProtection);
9698
const contentProtAttrParser = generateContentProtectionAttrParser(
9799
contentProtection,
98100
linearMemory,
@@ -103,7 +105,7 @@ export function generateAdaptationSetChildrenParser(
103105

104106
case TagName.EssentialProperty: {
105107
const essentialProperty = { attributes: {} };
106-
adaptationSetChildren.EssentialProperty.push(essentialProperty);
108+
pushChild(adaptationSetChildren, "EssentialProperty", essentialProperty);
107109

108110
const childrenParser = noop; // EssentialProperty have no sub-element
109111
const attributeParser = generateSchemeAttrParser(
@@ -116,7 +118,7 @@ export function generateAdaptationSetChildrenParser(
116118

117119
case TagName.InbandEventStream: {
118120
const inbandEvent = { attributes: {} };
119-
adaptationSetChildren.InbandEventStream.push(inbandEvent);
121+
pushChild(adaptationSetChildren, "InbandEventStream", inbandEvent);
120122

121123
const childrenParser = noop; // InbandEventStream have no sub-element
122124
const attributeParser = generateSchemeAttrParser(
@@ -128,20 +130,20 @@ export function generateAdaptationSetChildrenParser(
128130
}
129131

130132
case TagName.Representation: {
131-
const representationObj = {
133+
const representationObj: IRepresentationIntermediateRepresentation = {
132134
children: {
133-
BaseURL: [],
134-
ContentProtection: [],
135-
InbandEventStream: [],
136-
SegmentBase: [],
137-
SegmentList: [],
138-
SegmentTemplate: [],
139-
SupplementalProperty: [],
140-
EssentialProperty: [],
135+
BaseURL: emptyChildArray(),
136+
ContentProtection: emptyChildArray(),
137+
InbandEventStream: emptyChildArray(),
138+
SegmentBase: emptyChildArray(),
139+
SegmentList: emptyChildArray(),
140+
SegmentTemplate: emptyChildArray(),
141+
SupplementalProperty: emptyChildArray(),
142+
EssentialProperty: emptyChildArray(),
141143
},
142144
attributes: {},
143145
};
144-
adaptationSetChildren.Representation.push(representationObj);
146+
pushChild(adaptationSetChildren, "Representation", representationObj);
145147
const childrenParser = generateRepresentationChildrenParser(
146148
representationObj.children,
147149
linearMemory,
@@ -157,15 +159,15 @@ export function generateAdaptationSetChildrenParser(
157159

158160
case TagName.Role: {
159161
const role = { attributes: {} };
160-
adaptationSetChildren.Role.push(role);
162+
pushChild(adaptationSetChildren, "Role", role);
161163
const attributeParser = generateSchemeAttrParser(role.attributes, linearMemory);
162164
parsersStack.pushParsers(nodeId, noop, attributeParser);
163165
break;
164166
}
165167

166168
case TagName.SupplementalProperty: {
167169
const supplementalProperty = { attributes: {} };
168-
adaptationSetChildren.SupplementalProperty.push(supplementalProperty);
170+
pushChild(adaptationSetChildren, "SupplementalProperty", supplementalProperty);
169171
const attributeParser = generateSchemeAttrParser(
170172
supplementalProperty.attributes,
171173
linearMemory,
@@ -176,7 +178,7 @@ export function generateAdaptationSetChildrenParser(
176178

177179
case TagName.SegmentBase: {
178180
const segmentBaseObj = { children: { Initialization: [] }, attributes: {} };
179-
adaptationSetChildren.SegmentBase.push(segmentBaseObj);
181+
pushChild(adaptationSetChildren, "SegmentBase", segmentBaseObj);
180182
const attributeParser = generateSegmentBaseAttrParser(
181183
segmentBaseObj,
182184
linearMemory,
@@ -198,7 +200,7 @@ export function generateAdaptationSetChildrenParser(
198200
},
199201
attributes: {},
200202
};
201-
adaptationSetChildren.SegmentList.push(segmentListObj);
203+
pushChild(adaptationSetChildren, "SegmentList", segmentListObj);
202204
const childrenParser = generateSegmentListChildrenParser(
203205
segmentListObj,
204206
linearMemory,
@@ -216,7 +218,7 @@ export function generateAdaptationSetChildrenParser(
216218

217219
case TagName.SegmentTemplate: {
218220
const stObj = { children: { Initialization: [] }, attributes: {} };
219-
adaptationSetChildren.SegmentTemplate.push(stObj);
221+
pushChild(adaptationSetChildren, "SegmentTemplate", stObj);
220222
parsersStack.pushParsers(
221223
nodeId,
222224
generateSegmentTemplateChildrenParser(

‎src/parsers/manifest/dash/wasm-parser/ts/generators/Label.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { IAdaptationSetChildren } from "../../../node_parser_types.ts";
22
import type { IAttributeParser } from "../parsers_stack.ts";
33
import { AttributeName } from "../types.ts";
44
import { parseString } from "../utils.ts";
5+
import { pushChild } from "./lazy_child_array.ts";
56

67
export function generateLabelElementParser(
78
adaptationSet: IAdaptationSetChildren,
@@ -10,7 +11,7 @@ export function generateLabelElementParser(
1011
const textDecoder = new TextDecoder();
1112
return function onMPDAttribute(attr: AttributeName, ptr: number, len: number) {
1213
if (attr === AttributeName.Text) {
13-
adaptationSet.Label.push({
14+
pushChild(adaptationSet, "Label", {
1415
value: parseString(textDecoder, linearMemory.buffer, ptr, len),
1516
});
1617
}

‎src/parsers/manifest/dash/wasm-parser/ts/generators/Period.ts‎

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import noop from "../../../../../../utils/noop.ts";
1818
import type {
19+
IAdaptationSetIntermediateRepresentation,
1920
IEventStreamIntermediateRepresentation,
2021
IPeriodAttributes,
2122
IPeriodChildren,
@@ -34,6 +35,7 @@ import {
3435
generateEventStreamAttrParser,
3536
generateEventStreamChildrenParser,
3637
} from "./EventStream.ts";
38+
import { emptyChildArray } from "./lazy_child_array.ts";
3739
import {
3840
generateSegmentTemplateAttrParser,
3941
generateSegmentTemplateChildrenParser,
@@ -56,21 +58,21 @@ export function generatePeriodChildrenParser(
5658
return function onRootChildren(nodeId: number) {
5759
switch (nodeId) {
5860
case TagName.AdaptationSet: {
59-
const adaptationObj = {
61+
const adaptationObj: IAdaptationSetIntermediateRepresentation = {
6062
children: {
61-
BaseURL: [],
62-
Representation: [],
63-
Accessibility: [],
64-
ContentComponent: [],
65-
ContentProtection: [],
66-
EssentialProperty: [],
67-
InbandEventStream: [],
68-
Role: [],
69-
SupplementalProperty: [],
70-
SegmentBase: [],
71-
SegmentList: [],
72-
SegmentTemplate: [],
73-
Label: [],
63+
BaseURL: emptyChildArray(),
64+
Representation: emptyChildArray(),
65+
Accessibility: emptyChildArray(),
66+
ContentComponent: emptyChildArray(),
67+
ContentProtection: emptyChildArray(),
68+
EssentialProperty: emptyChildArray(),
69+
InbandEventStream: emptyChildArray(),
70+
Role: emptyChildArray(),
71+
SupplementalProperty: emptyChildArray(),
72+
SegmentBase: emptyChildArray(),
73+
SegmentList: emptyChildArray(),
74+
SegmentTemplate: emptyChildArray(),
75+
Label: emptyChildArray(),
7476
},
7577
attributes: {},
7678
};

‎src/parsers/manifest/dash/wasm-parser/ts/generators/Representation.ts‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { AttributeName, TagName } from "../types.ts";
2626
import { parseString } from "../utils.ts";
2727
import { generateBaseUrlAttrParser } from "./BaseURL.ts";
2828
import { generateContentProtectionAttrParser } from "./ContentProtection.ts";
29+
import { pushChild } from "./lazy_child_array.ts";
2930
import { generateSchemeAttrParser } from "./Scheme.ts";
3031
import {
3132
generateSegmentBaseAttrParser,
@@ -53,7 +54,7 @@ export function generateRepresentationChildrenParser(
5354
switch (nodeId) {
5455
case TagName.BaseURL: {
5556
const baseUrl = { value: "", attributes: {} };
56-
childrenObj.BaseURL.push(baseUrl);
57+
pushChild(childrenObj, "BaseURL", baseUrl);
5758
parsersStack.pushParsers(
5859
nodeId,
5960
noop,
@@ -67,7 +68,7 @@ export function generateRepresentationChildrenParser(
6768
children: { ["cenc:pssh"]: [] },
6869
attributes: {},
6970
};
70-
childrenObj.ContentProtection.push(contentProtection);
71+
pushChild(childrenObj, "ContentProtection", contentProtection);
7172
const contentProtAttrParser = generateContentProtectionAttrParser(
7273
contentProtection,
7374
linearMemory,
@@ -78,7 +79,7 @@ export function generateRepresentationChildrenParser(
7879

7980
case TagName.InbandEventStream: {
8081
const inbandEvent = { attributes: {} };
81-
childrenObj.InbandEventStream.push(inbandEvent);
82+
pushChild(childrenObj, "InbandEventStream", inbandEvent);
8283
parsersStack.pushParsers(
8384
nodeId,
8485
noop,
@@ -89,7 +90,7 @@ export function generateRepresentationChildrenParser(
8990

9091
case TagName.EssentialProperty: {
9192
const essentialProperty = { attributes: {} };
92-
childrenObj.EssentialProperty.push(essentialProperty);
93+
pushChild(childrenObj, "EssentialProperty", essentialProperty);
9394
const attributeParser = generateSchemeAttrParser(
9495
essentialProperty.attributes,
9596
linearMemory,
@@ -100,7 +101,7 @@ export function generateRepresentationChildrenParser(
100101

101102
case TagName.SupplementalProperty: {
102103
const supplementalProperty = { attributes: {} };
103-
childrenObj.SupplementalProperty.push(supplementalProperty);
104+
pushChild(childrenObj, "SupplementalProperty", supplementalProperty);
104105
const attributeParser = generateSchemeAttrParser(
105106
supplementalProperty.attributes,
106107
linearMemory,
@@ -111,7 +112,7 @@ export function generateRepresentationChildrenParser(
111112

112113
case TagName.SegmentBase: {
113114
const segmentBaseObj = { children: { Initialization: [] }, attributes: {} };
114-
childrenObj.SegmentBase.push(segmentBaseObj);
115+
pushChild(childrenObj, "SegmentBase", segmentBaseObj);
115116
const attributeParser = generateSegmentBaseAttrParser(
116117
segmentBaseObj,
117118
linearMemory,
@@ -130,7 +131,7 @@ export function generateRepresentationChildrenParser(
130131
children: { Initialization: [], SegmentURL: [] },
131132
attributes: {},
132133
};
133-
childrenObj.SegmentList.push(segmentListObj);
134+
pushChild(childrenObj, "SegmentList", segmentListObj);
134135
const childrenParser = generateSegmentListChildrenParser(
135136
segmentListObj,
136137
linearMemory,
@@ -148,7 +149,7 @@ export function generateRepresentationChildrenParser(
148149

149150
case TagName.SegmentTemplate: {
150151
const stObj = { children: { Initialization: [] }, attributes: {} };
151-
childrenObj.SegmentTemplate.push(stObj);
152+
pushChild(childrenObj, "SegmentTemplate", stObj);
152153
parsersStack.pushParsers(
153154
nodeId,
154155
generateSegmentTemplateChildrenParser(
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const EMPTY_CHILD_ARRAY: unknown[] = [];
2+
Object.freeze(EMPTY_CHILD_ARRAY);
3+
4+
/** Return the same empty array until a parser actually adds a child to it. */
5+
export function emptyChildArray<T>(): T[] {
6+
return EMPTY_CHILD_ARRAY as T[];
7+
}
8+
9+
/** Replace the shared empty array on first use, then append the child. */
10+
export function pushChild<T>(children: object, key: string, child: T): void {
11+
const childrenRecord = children as Record<string, unknown>;
12+
let childArray = childrenRecord[key] as T[];
13+
if (childArray === EMPTY_CHILD_ARRAY) {
14+
childArray = [];
15+
childrenRecord[key] = childArray;
16+
}
17+
childArray.push(child);
18+
}

0 commit comments

Comments
 (0)