• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16declare function print(arg:any): string;
17
18declare interface ArkTools {
19    timeInUs(arg: any): number;
20    isStableJsArray(arr: any[]): boolean;
21    getElementsKind(arr: any[]): number;
22}
23
24const REP_COUNT = 100_000;
25
26function initializeDenseArray(target: any, len: number, a: number, b: number, intOnly = true) {
27    for (let i = 0; i < len; i++) {
28        target[i] = (i * a + b) % len;
29        if (!intOnly && i % 2 == 0) {
30            target[i] += i / len; // int : double = 50% : 50%
31        }
32    }
33}
34
35function initializeSparseArray(target: any, len: number, nNonHole: number, a: number, b: number, intOnly = true) {
36    let last = 0;
37    const getNextElement = () => {
38        const res = (last * a + b) % len;
39        last = res;
40        return res;
41    }
42    for (let i = 0; i < nNonHole; i++) {
43        const index = getNextElement();
44        let value = getNextElement();
45        if (!intOnly && i % 2 == 0) {
46            value += i / len; // int : double = 50% : 50%
47        }
48        target[index] = value;
49    }
50}
51
52const result = {};
53
54function testArrayFunc(fnName: string, caseName: string, arr: number[]) {
55    print(`-------- Starts new test of Array.prototype.${fnName}()  --------`)
56    print(`Is arr stable array? ${ArkTools.isStableJsArray(arr)}`);
57    print(`arr.length = ${arr.length}. ElementsKind of arr: ${ArkTools.getElementsKind(arr)}`);
58    const someObj = { x: 1, y: 2, valueOf() { return 3; } };
59
60    let start: number;
61    let end: number;
62    let endExtra: number;
63
64    start = ArkTools.timeInUs();
65    for (let i = 0; i < REP_COUNT; i++) {
66        arr[fnName](i);
67    }
68    end = ArkTools.timeInUs();
69    for (let i = 0; i < REP_COUNT; i++) {
70        arr[fnName];
71        i;
72    }
73    endExtra = ArkTools.timeInUs();
74    const durationI = result[`${fnName}.${caseName}.intIndex`] = (2 * end - start - endExtra) / 1000;
75    print(`\tsearchElement is integer: ${durationI.toFixed(3)} ms.`);
76
77    start = ArkTools.timeInUs();
78    for (let i = 0; i < REP_COUNT; i++) {
79        arr[fnName](1.1 * i); // Expects early exit when target is not within int32 (90% chance)
80    }
81    end = ArkTools.timeInUs();
82    for (let i = 0; i < REP_COUNT; i++) {
83        arr[fnName];
84        1.1 * i;
85    }
86    endExtra = ArkTools.timeInUs();
87    const durationF = result[`${fnName}.${caseName}.doubleIndex`] = (2 * end - start - endExtra) / 1000;
88    print(`\tsearchElement is double: ${durationF.toFixed(3)} ms.`);
89
90    start = ArkTools.timeInUs();
91    for (let i = 0; i < REP_COUNT; i++) {
92        arr[fnName]("1"); // Expects early exit
93    }
94    end = ArkTools.timeInUs();
95    for (let i = 0; i < REP_COUNT; i++) {
96        arr[fnName];
97        "1";
98    }
99    endExtra = ArkTools.timeInUs();
100    const durationS = result[`${fnName}.${caseName}.stringIndex`] = (2 * end - start - endExtra) / 1000;
101    print(`\tsearchElement is string: ${durationS.toFixed(3)} ms.`);
102
103    start = ArkTools.timeInUs();
104    for (let i = 0; i < REP_COUNT; i++) {
105        arr[fnName](someObj); // Expects early exit
106    }
107    end = ArkTools.timeInUs();
108    for (let i = 0; i < REP_COUNT; i++) {
109        arr[fnName];
110        someObj;
111    }
112    endExtra = ArkTools.timeInUs();
113    const durationO = result[`${fnName}.${caseName}.objectIndex`] = (2 * end - start - endExtra) / 1000;
114    print(`\tsearchElement is object: ${durationO.toFixed(3)} ms.`);
115}
116
117for (const fnName of ['includes', 'indexOf', 'lastIndexOf']) {
118    {
119        const empty = [];
120        testArrayFunc(fnName, 'empty', empty);
121    }
122    {
123        const [ARR_LENGTH, N_NOT_HOLE_ELEMENTS, GEN_A, GEN_B] = [1499, 100, 233, 1];
124        const arr = new Array<number>(ARR_LENGTH);
125        initializeSparseArray(arr, ARR_LENGTH, N_NOT_HOLE_ELEMENTS, GEN_A, GEN_B);
126        testArrayFunc(fnName, `sparse.len${ARR_LENGTH}.generic`, arr); // ElementKind = 31 (GENERIC)
127    }
128    {
129        const [ARR_LENGTH, GEN_A, GEN_B] = [10007, 233, 1];
130        const arr = new Array<number>(ARR_LENGTH);
131        initializeDenseArray(arr, ARR_LENGTH, GEN_A, GEN_B);
132        testArrayFunc(fnName, `dense.len${ARR_LENGTH}.generic`, arr); // ElementKind = 31 (GENERIC)
133    }
134    for (const intOnly of [true, false]) {
135        {
136            const [ARR_LENGTH, GEN_A, GEN_B] = [17, 5, 1];
137            const arr: number[] = [];
138            initializeDenseArray(arr, ARR_LENGTH, GEN_A, GEN_B, intOnly);
139            testArrayFunc(fnName, `dense.len${ARR_LENGTH}.${intOnly ? 'int' : 'number'}`, arr);
140        }
141        {
142            const [ARR_LENGTH, N_NOT_HOLE_ELEMENTS, GEN_A, GEN_B] = [1499, 100, 233, 1];
143            const arr: number[] = [];
144            initializeSparseArray(arr, ARR_LENGTH, N_NOT_HOLE_ELEMENTS, GEN_A, GEN_B, intOnly);
145            testArrayFunc(fnName, `sparse.len${ARR_LENGTH}.hole${intOnly ? 'Int' : 'Number'}`, arr);
146        }
147        {
148            const [ARR_LENGTH, GEN_A, GEN_B] = [10007, 233, 1];
149            const arr: number[] = [];
150            initializeDenseArray(arr, ARR_LENGTH, GEN_A, GEN_B, intOnly);
151            testArrayFunc(fnName, `dense.len${ARR_LENGTH}.${intOnly ? 'int' : 'number'}`, arr);
152        }
153    }
154}
155
156print(JSON.stringify(result, null, 4));
157