Skip to content

Commit 36fee14

Browse files
committed
refactor: opt code
1 parent 96ecdab commit 36fee14

File tree

3 files changed

+168
-164
lines changed

3 files changed

+168
-164
lines changed

packages/core/src/DisorderedArray.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Utils } from "./Utils";
2+
13
/**
24
* High-performance unordered array, delete uses exchange method to improve performance, internal capacity only increases.
35
*/
@@ -87,7 +89,7 @@ export class DisorderedArray<T> {
8789
}
8890

8991
sort(compareFn: (a: T, b: T) => number): void {
90-
this._elements.sort(compareFn);
92+
Utils._quickSort(this._elements, 0, this.length, compareFn);
9193
}
9294

9395
garbageCollection(): void {

packages/core/src/RenderPipeline/RenderQueue.ts

+2-104
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Camera } from "../Camera";
22
import { Engine } from "../Engine";
33
import { Layer } from "../Layer";
4+
import { Utils } from "../Utils";
45
import { RenderQueueType, Shader } from "../shader";
56
import { ShaderMacroCollection } from "../shader/ShaderMacroCollection";
67
import { RenderContext } from "./RenderContext";
@@ -194,7 +195,7 @@ export class RenderQueue {
194195
* Sort the elements.
195196
*/
196197
sort(compareFunc: Function): void {
197-
this._quickSort(this.elements, 0, this.elements.length, compareFunc);
198+
Utils._quickSort(this.elements, 0, this.elements.length, compareFunc);
198199
}
199200

200201
/**
@@ -204,107 +205,4 @@ export class RenderQueue {
204205
_initSpriteBatcher(engine: Engine): void {
205206
this._spriteBatcher = new SpriteBatcher(engine);
206207
}
207-
208-
/**
209-
* @remarks
210-
* Modified based on v8.
211-
* https://github.com/v8/v8/blob/7.2-lkgr/src/js/array.js
212-
*/
213-
private _quickSort<T>(a: T[], from: number, to: number, compareFunc: Function): void {
214-
while (true) {
215-
// Insertion sort is faster for short arrays.
216-
if (to - from <= 10) {
217-
this._insertionSort(a, from, to, compareFunc);
218-
return;
219-
}
220-
const third_index = (from + to) >> 1;
221-
// Find a pivot as the median of first, last and middle element.
222-
let v0 = a[from];
223-
let v1 = a[to - 1];
224-
let v2 = a[third_index];
225-
const c01 = compareFunc(v0, v1);
226-
if (c01 > 0) {
227-
// v1 < v0, so swap them.
228-
const tmp = v0;
229-
v0 = v1;
230-
v1 = tmp;
231-
} // v0 <= v1.
232-
const c02 = compareFunc(v0, v2);
233-
if (c02 >= 0) {
234-
// v2 <= v0 <= v1.
235-
const tmp = v0;
236-
v0 = v2;
237-
v2 = v1;
238-
v1 = tmp;
239-
} else {
240-
// v0 <= v1 && v0 < v2
241-
const c12 = compareFunc(v1, v2);
242-
if (c12 > 0) {
243-
// v0 <= v2 < v1
244-
const tmp = v1;
245-
v1 = v2;
246-
v2 = tmp;
247-
}
248-
}
249-
// v0 <= v1 <= v2
250-
a[from] = v0;
251-
a[to - 1] = v2;
252-
const pivot = v1;
253-
let low_end = from + 1; // Upper bound of elements lower than pivot.
254-
let high_start = to - 1; // Lower bound of elements greater than pivot.
255-
a[third_index] = a[low_end];
256-
a[low_end] = pivot;
257-
258-
// From low_end to i are elements equal to pivot.
259-
// From i to high_start are elements that haven't been compared yet.
260-
partition: for (let i = low_end + 1; i < high_start; i++) {
261-
let element = a[i];
262-
let order = compareFunc(element, pivot);
263-
if (order < 0) {
264-
a[i] = a[low_end];
265-
a[low_end] = element;
266-
low_end++;
267-
} else if (order > 0) {
268-
do {
269-
high_start--;
270-
if (high_start == i) break partition;
271-
const top_elem = a[high_start];
272-
order = compareFunc(top_elem, pivot);
273-
} while (order > 0);
274-
a[i] = a[high_start];
275-
a[high_start] = element;
276-
if (order < 0) {
277-
element = a[i];
278-
a[i] = a[low_end];
279-
a[low_end] = element;
280-
low_end++;
281-
}
282-
}
283-
}
284-
if (to - high_start < low_end - from) {
285-
this._quickSort(a, high_start, to, compareFunc);
286-
to = low_end;
287-
} else {
288-
this._quickSort(a, from, low_end, compareFunc);
289-
from = high_start;
290-
}
291-
}
292-
}
293-
294-
private _insertionSort<T>(a: T[], from: number, to: number, compareFunc: Function): void {
295-
for (let i = from + 1; i < to; i++) {
296-
let j;
297-
const element = a[i];
298-
for (j = i - 1; j >= from; j--) {
299-
const tmp = a[j];
300-
const order = compareFunc(tmp, element);
301-
if (order > 0) {
302-
a[j + 1] = tmp;
303-
} else {
304-
break;
305-
}
306-
}
307-
a[j + 1] = element;
308-
}
309-
}
310208
}

packages/core/src/Utils.ts

+163-59
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,6 @@
11
import { Matrix } from "@galacean/engine-math";
22

33
export class Utils {
4-
/**
5-
* @internal
6-
*/
7-
static _floatMatrixMultiply(left: Matrix, re: Float32Array, rOffset: number, oe: Float32Array, offset: number): void {
8-
const le = left.elements;
9-
10-
// prettier-ignore
11-
const l11 = le[0], l12 = le[1], l13 = le[2], l14 = le[3],
12-
l21 = le[4], l22 = le[5], l23 = le[6], l24 = le[7],
13-
l31 = le[8], l32 = le[9], l33 = le[10], l34 = le[11],
14-
l41 = le[12], l42 = le[13], l43 = le[14], l44 = le[15];
15-
16-
// prettier-ignore
17-
const r11 = re[rOffset], r12 = re[rOffset + 1], r13 = re[rOffset + 2], r14 = re[rOffset + 3],
18-
r21 = re[rOffset + 4], r22 = re[rOffset + 5], r23 = re[rOffset + 6], r24 = re[rOffset + 7],
19-
r31 = re[rOffset + 8], r32 = re[rOffset + 9], r33 = re[rOffset + 10], r34 = re[rOffset + 11],
20-
r41 = re[rOffset + 12], r42 = re[rOffset + 13], r43 = re[rOffset + 14], r44 = re[rOffset + 15];
21-
22-
oe[offset] = l11 * r11 + l21 * r12 + l31 * r13 + l41 * r14;
23-
oe[offset + 1] = l12 * r11 + l22 * r12 + l32 * r13 + l42 * r14;
24-
oe[offset + 2] = l13 * r11 + l23 * r12 + l33 * r13 + l43 * r14;
25-
oe[offset + 3] = l14 * r11 + l24 * r12 + l34 * r13 + l44 * r14;
26-
27-
oe[offset + 4] = l11 * r21 + l21 * r22 + l31 * r23 + l41 * r24;
28-
oe[offset + 5] = l12 * r21 + l22 * r22 + l32 * r23 + l42 * r24;
29-
oe[offset + 6] = l13 * r21 + l23 * r22 + l33 * r23 + l43 * r24;
30-
oe[offset + 7] = l14 * r21 + l24 * r22 + l34 * r23 + l44 * r24;
31-
32-
oe[offset + 8] = l11 * r31 + l21 * r32 + l31 * r33 + l41 * r34;
33-
oe[offset + 9] = l12 * r31 + l22 * r32 + l32 * r33 + l42 * r34;
34-
oe[offset + 10] = l13 * r31 + l23 * r32 + l33 * r33 + l43 * r34;
35-
oe[offset + 11] = l14 * r31 + l24 * r32 + l34 * r33 + l44 * r34;
36-
37-
oe[offset + 12] = l11 * r41 + l21 * r42 + l31 * r43 + l41 * r44;
38-
oe[offset + 13] = l12 * r41 + l22 * r42 + l32 * r43 + l42 * r44;
39-
oe[offset + 14] = l13 * r41 + l23 * r42 + l33 * r43 + l43 * r44;
40-
oe[offset + 15] = l14 * r41 + l24 * r42 + l34 * r43 + l44 * r44;
41-
}
42-
43-
/**
44-
* @internal
45-
* Simplify lodash get: https://github.com/lodash/lodash/blob/master/get.js.
46-
* @param target - The object to query.
47-
* @param path - The path of the property to get.
48-
* @returns Returns the resolved value.
49-
*/
50-
static _reflectGet(target: Object, path: string) {
51-
const pathArr = this._stringToPath(path);
52-
53-
let object = target;
54-
let index = 0;
55-
const length = pathArr.length;
56-
57-
while (object != null && index < length) {
58-
object = object[pathArr[index++]];
59-
}
60-
return index && index == length ? object : undefined;
61-
}
62-
634
/**
645
* Fast remove an element from array.
656
* @param array - Array
@@ -127,6 +68,152 @@ export class Utils {
12768
return baseUrl.substring(0, baseUrl.lastIndexOf("/") + 1) + this._formatRelativePath(relativeUrl);
12869
}
12970

71+
/**
72+
* @internal
73+
*/
74+
static _floatMatrixMultiply(left: Matrix, re: Float32Array, rOffset: number, oe: Float32Array, offset: number): void {
75+
const le = left.elements;
76+
77+
// prettier-ignore
78+
const l11 = le[0], l12 = le[1], l13 = le[2], l14 = le[3],
79+
l21 = le[4], l22 = le[5], l23 = le[6], l24 = le[7],
80+
l31 = le[8], l32 = le[9], l33 = le[10], l34 = le[11],
81+
l41 = le[12], l42 = le[13], l43 = le[14], l44 = le[15];
82+
83+
// prettier-ignore
84+
const r11 = re[rOffset], r12 = re[rOffset + 1], r13 = re[rOffset + 2], r14 = re[rOffset + 3],
85+
r21 = re[rOffset + 4], r22 = re[rOffset + 5], r23 = re[rOffset + 6], r24 = re[rOffset + 7],
86+
r31 = re[rOffset + 8], r32 = re[rOffset + 9], r33 = re[rOffset + 10], r34 = re[rOffset + 11],
87+
r41 = re[rOffset + 12], r42 = re[rOffset + 13], r43 = re[rOffset + 14], r44 = re[rOffset + 15];
88+
89+
oe[offset] = l11 * r11 + l21 * r12 + l31 * r13 + l41 * r14;
90+
oe[offset + 1] = l12 * r11 + l22 * r12 + l32 * r13 + l42 * r14;
91+
oe[offset + 2] = l13 * r11 + l23 * r12 + l33 * r13 + l43 * r14;
92+
oe[offset + 3] = l14 * r11 + l24 * r12 + l34 * r13 + l44 * r14;
93+
94+
oe[offset + 4] = l11 * r21 + l21 * r22 + l31 * r23 + l41 * r24;
95+
oe[offset + 5] = l12 * r21 + l22 * r22 + l32 * r23 + l42 * r24;
96+
oe[offset + 6] = l13 * r21 + l23 * r22 + l33 * r23 + l43 * r24;
97+
oe[offset + 7] = l14 * r21 + l24 * r22 + l34 * r23 + l44 * r24;
98+
99+
oe[offset + 8] = l11 * r31 + l21 * r32 + l31 * r33 + l41 * r34;
100+
oe[offset + 9] = l12 * r31 + l22 * r32 + l32 * r33 + l42 * r34;
101+
oe[offset + 10] = l13 * r31 + l23 * r32 + l33 * r33 + l43 * r34;
102+
oe[offset + 11] = l14 * r31 + l24 * r32 + l34 * r33 + l44 * r34;
103+
104+
oe[offset + 12] = l11 * r41 + l21 * r42 + l31 * r43 + l41 * r44;
105+
oe[offset + 13] = l12 * r41 + l22 * r42 + l32 * r43 + l42 * r44;
106+
oe[offset + 14] = l13 * r41 + l23 * r42 + l33 * r43 + l43 * r44;
107+
oe[offset + 15] = l14 * r41 + l24 * r42 + l34 * r43 + l44 * r44;
108+
}
109+
110+
/**
111+
* @internal
112+
* Simplify lodash get: https://github.com/lodash/lodash/blob/master/get.js.
113+
* @param target - The object to query.
114+
* @param path - The path of the property to get.
115+
* @returns Returns the resolved value.
116+
*/
117+
static _reflectGet(target: Object, path: string) {
118+
const pathArr = this._stringToPath(path);
119+
120+
let object = target;
121+
let index = 0;
122+
const length = pathArr.length;
123+
124+
while (object != null && index < length) {
125+
object = object[pathArr[index++]];
126+
}
127+
return index && index == length ? object : undefined;
128+
}
129+
130+
/**
131+
* @internal
132+
* @remarks
133+
* Modified based on v8.
134+
* https://github.com/v8/v8/blob/7.2-lkgr/src/js/array.js
135+
*/
136+
static _quickSort<T>(a: T[], from: number, to: number, compareFunc: Function): void {
137+
while (true) {
138+
// Insertion sort is faster for short arrays.
139+
if (to - from <= 10) {
140+
this._insertionSort(a, from, to, compareFunc);
141+
return;
142+
}
143+
const third_index = (from + to) >> 1;
144+
// Find a pivot as the median of first, last and middle element.
145+
let v0 = a[from];
146+
let v1 = a[to - 1];
147+
let v2 = a[third_index];
148+
const c01 = compareFunc(v0, v1);
149+
if (c01 > 0) {
150+
// v1 < v0, so swap them.
151+
const tmp = v0;
152+
v0 = v1;
153+
v1 = tmp;
154+
} // v0 <= v1.
155+
const c02 = compareFunc(v0, v2);
156+
if (c02 >= 0) {
157+
// v2 <= v0 <= v1.
158+
const tmp = v0;
159+
v0 = v2;
160+
v2 = v1;
161+
v1 = tmp;
162+
} else {
163+
// v0 <= v1 && v0 < v2
164+
const c12 = compareFunc(v1, v2);
165+
if (c12 > 0) {
166+
// v0 <= v2 < v1
167+
const tmp = v1;
168+
v1 = v2;
169+
v2 = tmp;
170+
}
171+
}
172+
// v0 <= v1 <= v2
173+
a[from] = v0;
174+
a[to - 1] = v2;
175+
const pivot = v1;
176+
let low_end = from + 1; // Upper bound of elements lower than pivot.
177+
let high_start = to - 1; // Lower bound of elements greater than pivot.
178+
a[third_index] = a[low_end];
179+
a[low_end] = pivot;
180+
181+
// From low_end to i are elements equal to pivot.
182+
// From i to high_start are elements that haven't been compared yet.
183+
partition: for (let i = low_end + 1; i < high_start; i++) {
184+
let element = a[i];
185+
let order = compareFunc(element, pivot);
186+
if (order < 0) {
187+
a[i] = a[low_end];
188+
a[low_end] = element;
189+
low_end++;
190+
} else if (order > 0) {
191+
do {
192+
high_start--;
193+
if (high_start == i) break partition;
194+
const top_elem = a[high_start];
195+
order = compareFunc(top_elem, pivot);
196+
} while (order > 0);
197+
a[i] = a[high_start];
198+
a[high_start] = element;
199+
if (order < 0) {
200+
element = a[i];
201+
a[i] = a[low_end];
202+
a[low_end] = element;
203+
low_end++;
204+
}
205+
}
206+
}
207+
if (to - high_start < low_end - from) {
208+
this._quickSort(a, high_start, to, compareFunc);
209+
to = low_end;
210+
} else {
211+
this._quickSort(a, from, low_end, compareFunc);
212+
from = high_start;
213+
}
214+
}
215+
}
216+
130217
private static _stringToPath(string): string[] {
131218
const result = [];
132219
if (string.charCodeAt(0) === charCodeOfDot) {
@@ -156,6 +243,23 @@ export class Utils {
156243
}, [])
157244
.join("/");
158245
}
246+
247+
private static _insertionSort<T>(a: T[], from: number, to: number, compareFunc: Function): void {
248+
for (let i = from + 1; i < to; i++) {
249+
let j;
250+
const element = a[i];
251+
for (j = i - 1; j >= from; j--) {
252+
const tmp = a[j];
253+
const order = compareFunc(tmp, element);
254+
if (order > 0) {
255+
a[j + 1] = tmp;
256+
} else {
257+
break;
258+
}
259+
}
260+
a[j + 1] = element;
261+
}
262+
}
159263
}
160264

161265
const charCodeOfDot = ".".charCodeAt(0);

0 commit comments

Comments
 (0)