Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(performance): Eliminate use of ES6 generators #4092

Merged
merged 2 commits into from Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions build/conformance.textproto
Expand Up @@ -320,3 +320,16 @@ requirement: {
"instead."
whitelist_regexp: "lib/net/http_fetch_plugin.js"
}

# Disallow the use of generators, which are a major performance issue. See
# https://github.com/shaka-project/shaka-player/issues/4062#issuecomment-1079428268
requirement: {
type: BANNED_CODE_PATTERN
value:
"/** @param {*} x */ "
"function *template(x) { yield x; }"
error_message:
"ES6 generators are a major performance issue! Find another solution. "
"See also https://bit.ly/3wAsoj5"
whitelist_regexp: "node_modules/"
}
8 changes: 5 additions & 3 deletions lib/cea/cea708_service.js
Expand Up @@ -300,17 +300,19 @@ shaka.cea.Cea708Service = class {
/**
* Yields each non-null window specified in the 8-bit bitmap.
* @param {number} bitmap 8 bits corresponding to each of the 8 windows.
* @return {!Iterable.<number>}
* @return {!Array.<number>}
* @private
*/
* getSpecifiedWindowIds_(bitmap) {
getSpecifiedWindowIds_(bitmap) {
const ids = [];
for (let i = 0; i < 8; i++) {
const windowSpecified = (bitmap & 0x01) === 0x01;
if (windowSpecified && this.windows_[i]) {
yield i;
ids.push(i);
}
bitmap >>= 1;
}
return ids;
}

/**
Expand Down
9 changes: 6 additions & 3 deletions lib/cea/sei_processor.js
Expand Up @@ -14,9 +14,10 @@ shaka.cea.SeiProcessor = class {
/**
* Processes supplemental enhancement information data.
* @param {!Uint8Array} naluData NALU from which SEI data is to be processed.
* @return {!Iterable.<!Uint8Array>}
* @return {!Array.<!Uint8Array>}
*/
* process(naluData) {
process(naluData) {
const seiPayloads = [];
const naluClone = this.removeEmu(naluData);

// The following is an implementation of section 7.3.2.3.1
Expand All @@ -41,10 +42,12 @@ shaka.cea.SeiProcessor = class {
// Payload type 4 is user_data_registered_itu_t_t35, as per the H.264
// spec. This payload type contains caption data.
if (payloadType == 0x04) {
yield naluClone.subarray(offset, offset + payloadSize);
seiPayloads.push(naluClone.subarray(offset, offset + payloadSize));
}
offset += payloadSize;
}

return seiPayloads;
}


Expand Down
3 changes: 1 addition & 2 deletions lib/dash/segment_list.js
Expand Up @@ -15,7 +15,6 @@ goog.require('shaka.media.SegmentIndex');
goog.require('shaka.media.SegmentReference');
goog.require('shaka.util.Error');
goog.require('shaka.util.Functional');
goog.require('shaka.util.Iterables');
goog.require('shaka.util.ManifestParserUtils');
goog.require('shaka.util.XmlUtils');
goog.requireType('shaka.dash.DashParser');
Expand Down Expand Up @@ -222,7 +221,7 @@ shaka.dash.SegmentList = class {
/** @type {!Array.<!shaka.media.SegmentReference>} */
const references = [];
let prevEndTime = info.startTime;
for (const i of shaka.util.Iterables.range(max)) {
for (let i = 0; i < max; i++) {
const segment = info.mediaSegments[i];
const mediaUri = ManifestParserUtils.resolveUris(
baseUris, [segment.mediaUri]);
Expand Down
12 changes: 7 additions & 5 deletions lib/hls/hls_parser.js
Expand Up @@ -30,7 +30,6 @@ goog.require('shaka.util.CmcdManager');
goog.require('shaka.util.Error');
goog.require('shaka.util.FakeEvent');
goog.require('shaka.util.Functional');
goog.require('shaka.util.Iterables');
goog.require('shaka.util.LanguageUtils');
goog.require('shaka.util.ManifestParserUtils');
goog.require('shaka.util.MimeUtils');
Expand Down Expand Up @@ -1869,8 +1868,8 @@ shaka.hls.HlsParser = class {
// Create SegmentReferences for the partial segments.
const partialSegmentRefs = [];
if (this.lowLatencyMode_ && hlsSegment.partialSegments.length) {
const enumerate = (it) => shaka.util.Iterables.enumerate(it);
for (const {i, item} of enumerate(hlsSegment.partialSegments)) {
for (let i = 0; i < hlsSegment.partialSegments.length; i++) {
const item = hlsSegment.partialSegments[i];
const pPreviousReference = i == 0 ?
previousReference : partialSegmentRefs[partialSegmentRefs.length - 1];
const pStartTime = (i == 0) ? startTime : pPreviousReference.endTime;
Expand All @@ -1891,6 +1890,9 @@ shaka.hls.HlsParser = class {
this.parseByteRange_(pPreviousReference, pByterange);
}
const pUri = item.getAttributeValue('URI');
if (!pUri) {
continue;
}
const pAbsoluteUri = shaka.hls.Utils.constructAbsoluteUri(
absoluteMediaPlaylistUri, pUri);

Expand Down Expand Up @@ -2066,8 +2068,8 @@ shaka.hls.HlsParser = class {
/** @type {!Array.<!shaka.media.SegmentReference>} */
const references = [];

const enumerate = (it) => shaka.util.Iterables.enumerate(it);
for (const {i, item} of enumerate(hlsSegments)) {
for (let i = 0; i < hlsSegments.length; i++) {
const item = hlsSegments[i];
const previousReference = references[references.length - 1];
const startTime =
(i == 0) ? firstStartTime : previousReference.endTime;
Expand Down
6 changes: 3 additions & 3 deletions lib/hls/manifest_text_parser.js
Expand Up @@ -13,7 +13,6 @@ goog.require('shaka.hls.Segment');
goog.require('shaka.hls.Tag');
goog.require('shaka.hls.Utils');
goog.require('shaka.util.Error');
goog.require('shaka.util.Iterables');
goog.require('shaka.util.StringUtils');
goog.require('shaka.util.TextParser');

Expand Down Expand Up @@ -82,8 +81,9 @@ shaka.hls.ManifestTextParser = class {
const tags = [];
// Initialize to "true" to skip the first element.
skip = true;
const enumerate = (it) => shaka.util.Iterables.enumerate(it);
for (const {i, item: line, next} of enumerate(lines)) {
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const next = lines[i + 1];
// Skip comments
if (shaka.hls.Utils.isComment(line) || skip) {
skip = false;
Expand Down
3 changes: 1 addition & 2 deletions lib/media/adaptation_set.js
Expand Up @@ -8,7 +8,6 @@ goog.provide('shaka.media.AdaptationSet');

goog.require('goog.asserts');
goog.require('shaka.log');
goog.require('shaka.util.Iterables');
goog.require('shaka.util.MimeUtils');


Expand Down Expand Up @@ -215,7 +214,7 @@ shaka.media.AdaptationSet = class {
codecsA.sort();
codecsB.sort();

for (const i of shaka.util.Iterables.range(codecsA.length)) {
for (let i = 0; i < codecsA.length; i++) {
if (codecsA[i] != codecsB[i]) {
return false;
}
Expand Down
5 changes: 1 addition & 4 deletions lib/media/mp4_segment_index_parser.js
Expand Up @@ -11,8 +11,6 @@ goog.require('shaka.log');
goog.require('shaka.media.InitSegmentReference');
goog.require('shaka.media.SegmentReference');
goog.require('shaka.util.Error');
goog.require('shaka.util.Functional');
goog.require('shaka.util.Iterables');
goog.require('shaka.util.Mp4Parser');


Expand Down Expand Up @@ -123,8 +121,7 @@ shaka.media.Mp4SegmentIndexParser = class {
let unscaledStartTime = earliestPresentationTime;
let startByte = sidxOffset + box.size + firstOffset;

for (const _ of shaka.util.Iterables.range(referenceCount)) {
shaka.util.Functional.ignored(_);
for (let i = 0; i < referenceCount; i++) {
// |chunk| is 1 bit for |referenceType|, and 31 bits for |referenceSize|.
const chunk = box.reader.readUint32();
const referenceType = (chunk & 0x80000000) >>> 31;
Expand Down
4 changes: 1 addition & 3 deletions lib/media/time_ranges_utils.js
Expand Up @@ -6,8 +6,6 @@

goog.provide('shaka.media.TimeRangesUtils');

goog.require('shaka.util.Iterables');


/**
* @summary A set of utility functions for dealing with TimeRanges objects.
Expand Down Expand Up @@ -157,7 +155,7 @@ shaka.media.TimeRangesUtils = class {
return [];
}
const ret = [];
for (const i of shaka.util.Iterables.range(b.length)) {
for (let i = 0; i < b.length; i++) {
ret.push({start: b.start(i), end: b.end(i)});
}
return ret;
Expand Down
5 changes: 2 additions & 3 deletions lib/polyfill/all.js
Expand Up @@ -7,7 +7,6 @@
goog.provide('shaka.polyfill');

goog.require('shaka.log');
goog.require('shaka.util.Iterables');


/**
Expand Down Expand Up @@ -40,8 +39,8 @@ shaka.polyfill = class {
*/
static register(polyfill, priority) {
const newItem = {priority: priority || 0, callback: polyfill};
const enumerate = (it) => shaka.util.Iterables.enumerate(it);
for (const {i, item} of enumerate(shaka.polyfill.polyfills_)) {
for (let i = 0; i < shaka.polyfill.polyfills_.length; i++) {
const item = shaka.polyfill.polyfills_[i];
if (item.priority < newItem.priority) {
shaka.polyfill.polyfills_.splice(i, 0, newItem);
return;
Expand Down
4 changes: 1 addition & 3 deletions lib/util/buffer_utils.js
Expand Up @@ -6,8 +6,6 @@

goog.provide('shaka.util.BufferUtils');

goog.require('shaka.util.Iterables');


/**
* @summary A set of BufferSource utility functions.
Expand Down Expand Up @@ -45,7 +43,7 @@ shaka.util.BufferUtils = class {

const uint8A = shaka.util.BufferUtils.toUint8(arr1);
const uint8B = shaka.util.BufferUtils.toUint8(arr2);
for (const i of shaka.util.Iterables.range(arr1.byteLength)) {
for (let i = 0; i < arr1.byteLength; i++) {
if (uint8A[i] != uint8B[i]) {
return false;
}
Expand Down
6 changes: 3 additions & 3 deletions lib/util/ebml_parser.js
Expand Up @@ -11,7 +11,6 @@ goog.require('goog.asserts');
goog.require('shaka.util.BufferUtils');
goog.require('shaka.util.DataViewReader');
goog.require('shaka.util.Error');
goog.require('shaka.util.Iterables');


/**
Expand Down Expand Up @@ -157,7 +156,8 @@ shaka.util.EbmlParser = class {
}

let value = 0;
for (const {item, i} of shaka.util.Iterables.enumerate(vint)) {
for (let i = 0; i < vint.length; i++) {
const item = vint[i];
if (i == 0) {
// Mask out the first few bits of |vint|'s first byte to get the most
// significant bits of |vint|'s value. If |vint| is 8 bytes wide then
Expand Down Expand Up @@ -267,7 +267,7 @@ shaka.util.EbmlElement = class {

let value = 0;

for (const i of shaka.util.Iterables.range(this.dataView_.byteLength)) {
for (let i = 0; i < this.dataView_.byteLength; i++) {
const chunk = this.dataView_.getUint8(i);
value = (256 * value) + chunk;
}
Expand Down
46 changes: 0 additions & 46 deletions lib/util/iterables.js
Expand Up @@ -75,50 +75,4 @@ shaka.util.Iterables = class {
}
return out;
}

/**
* Returns an iterable that contains numbers in the range [0, end).
*
* @param {number} end The exclusive end of the list.
* @return {!Iterable.<number>}
*/
static* range(end) {
for (let i = 0; i < end; i++) {
yield i;
}
}

/**
* Iterates over an iterable object and includes additional info about each
* item:
* - The zero-based index of the element.
* - The next item in the list, if it exists.
* - The previous item in the list, if it exists.
*
* @param {!Iterable.<T>} iterable
* @return {!Iterable.<
* {i: number, item: T, prev: (T|undefined), next: (T|undefined)}>}
* @template T
*/
static* enumerate(iterable) {
// Since we want the "next" item, we need to skip the first item and return
// elements one in the past. So as we iterate, we are getting the "next"
// element and yielding the one from the previous iteration.
let i = -1;
let prev = undefined;
let item = undefined;
for (const next of iterable) {
if (i >= 0) {
yield {i, item, prev, next};
}
i++;
prev = item;
item = next;
}
if (i != -1) {
// If it's still -1, there were no items. Otherwise we need to yield
// the last item.
yield {i, prev, item, next: undefined};
}
}
};
5 changes: 1 addition & 4 deletions lib/util/mp4_box_parsers.js
Expand Up @@ -7,8 +7,6 @@
goog.provide('shaka.util.Mp4BoxParsers');

goog.require('shaka.util.DataViewReader');
goog.require('shaka.util.Functional');
goog.require('shaka.util.Iterables');

shaka.util.Mp4BoxParsers = class {
/**
Expand Down Expand Up @@ -125,8 +123,7 @@ shaka.util.Mp4BoxParsers = class {
reader.skip(4);
}

for (const _ of shaka.util.Iterables.range(sampleCount)) {
shaka.util.Functional.ignored(_);
for (let i = 0; i < sampleCount; i++) {
/** @type {shaka.util.ParsedTRUNSample} */
const sample = {
sampleDuration: null,
Expand Down
5 changes: 1 addition & 4 deletions lib/util/mp4_parser.js
Expand Up @@ -9,8 +9,6 @@ goog.provide('shaka.util.Mp4Parser');
goog.require('goog.asserts');
goog.require('shaka.log');
goog.require('shaka.util.DataViewReader');
goog.require('shaka.util.Functional');
goog.require('shaka.util.Iterables');


/**
Expand Down Expand Up @@ -229,8 +227,7 @@ shaka.util.Mp4Parser = class {
// start position. The header size varies.
const headerSize = shaka.util.Mp4Parser.headerSize(box);
const count = box.reader.readUint32();
for (const _ of shaka.util.Iterables.range(count)) {
shaka.util.Functional.ignored(_);
for (let i = 0; i < count; i++) {
box.parser.parseNext(box.start + headerSize, box.reader, box.partialOkay);
if (box.parser.done_) {
break;
Expand Down