Add types to scripts and config files (#1277)

Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1277

Now that we have some TypeScript infra set up, move scripts (mainly the benchmarking one) and config files to TypeScript.

Starts to move away a bit from the magic globals used in the JS environment.

Reviewed By: yungsters

Differential Revision: D45511176

fbshipit-source-id: 09bb1117a1b331758ed9d210e82d5b250577df81
This commit is contained in:
Nick Gerleman
2023-05-04 08:11:04 -07:00
committed by Facebook GitHub Bot
parent 19aed1d63e
commit 44ea3c1555
13 changed files with 438 additions and 137 deletions

View File

@@ -5,6 +5,9 @@
* LICENSE file in the root directory of this source tree.
*/
import { getMeasureCounter } from "../tools/MeasureCounter";
import { Yoga, YGBENCHMARK } from "../tools/globals";
const ITERATIONS = 2000;
YGBENCHMARK("Stack with flex", () => {
@@ -12,7 +15,7 @@ YGBENCHMARK("Stack with flex", () => {
root.setWidth(100);
root.setHeight(100);
const measureCounter = getMeasureCounter(Yoga);
const measureCounter = getMeasureCounter();
for (let i = 0; i < ITERATIONS; i++) {
const child = Yoga.Node.create();
@@ -21,14 +24,14 @@ YGBENCHMARK("Stack with flex", () => {
root.insertChild(child, 0);
}
root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR);
root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR);
root.freeRecursive();
});
YGBENCHMARK("Align stretch in undefined axis", () => {
const root = Yoga.Node.create();
const measureCounter = getMeasureCounter(Yoga);
const measureCounter = getMeasureCounter();
for (let i = 0; i < ITERATIONS; i++) {
const child = Yoga.Node.create();
@@ -37,14 +40,14 @@ YGBENCHMARK("Align stretch in undefined axis", () => {
root.insertChild(child, 0);
}
root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR);
root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR);
root.freeRecursive();
});
YGBENCHMARK("Nested flex", () => {
const root = Yoga.Node.create();
const measureCounter = getMeasureCounter(Yoga);
const measureCounter = getMeasureCounter();
const iterations = Math.pow(ITERATIONS, 1 / 2);
@@ -61,7 +64,7 @@ YGBENCHMARK("Nested flex", () => {
}
}
root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR);
root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR);
root.freeRecursive();
});
@@ -104,6 +107,6 @@ YGBENCHMARK("Huge nested layout", () => {
}
}
root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR);
root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR);
root.freeRecursive();
});

View File

@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
import { getMeasureCounterMax } from "./tools/MeasureCounter";
test("measure_once_single_flexible_child", () => {
const root = Yoga.Node.create();
root.setFlexDirection(Yoga.FLEX_DIRECTION_ROW);

View File

@@ -5,12 +5,14 @@
* LICENSE file in the root directory of this source tree.
*/
import { getMeasureCounter } from "./tools/MeasureCounter";
test("dont_measure_single_grow_shrink_child", () => {
const root = Yoga.Node.create();
root.setWidth(100);
root.setHeight(100);
const measureCounter = getMeasureCounter(Yoga, null, 100, 100);
const measureCounter = getMeasureCounter(null, 100, 100);
const root_child0 = Yoga.Node.create();
root_child0.setMeasureFunc(measureCounter.inc);
@@ -25,9 +27,9 @@ test("dont_measure_single_grow_shrink_child", () => {
});
test("dont_fail_with_incomplete_measure_dimensions", () => {
const heightOnlyCallback = getMeasureCounter(Yoga, () => ({ height: 10 }));
const widthOnlyCallback = getMeasureCounter(Yoga, () => ({ width: 10 }));
const emptyCallback = getMeasureCounter(Yoga, () => ({}));
const heightOnlyCallback = getMeasureCounter(() => ({ height: 10 }));
const widthOnlyCallback = getMeasureCounter(() => ({ width: 10 }));
const emptyCallback = getMeasureCounter(() => ({}));
const root = Yoga.Node.create();
root.setWidth(100);

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env ts-node
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import path from "path";
const WARMUP_ITERATIONS = 3;
const BENCHMARK_ITERATIONS = 10;
const testFiles = process.argv.slice(2);
const testResults = new Map<string, Map<string, number>>();
for (const type of ["asmjs", "wasm"]) {
globalThis.Yoga = require(type === "asmjs"
? "../../dist/entrypoint/asmjs-sync"
: "../../dist/entrypoint/wasm-sync");
for (const file of testFiles) {
globalThis.YGBENCHMARK = (name: string, fn: () => void) => {
let testEntry = testResults.get(name);
if (testEntry === undefined)
testResults.set(name, (testEntry = new Map()));
for (let t = 0; t < WARMUP_ITERATIONS; ++t) fn();
const start = Date.now();
for (let t = 0; t < BENCHMARK_ITERATIONS; ++t) fn();
const end = Date.now();
testEntry.set(type, (end - start) / BENCHMARK_ITERATIONS);
};
const modulePath = path.resolve(file);
delete require.cache[require.resolve("../tools/globals")];
delete require.cache[modulePath];
require(modulePath);
}
}
console.log(
`Note: those tests are independants; there is no time relation to be expected between them`
);
for (const [name, results] of testResults) {
console.log();
const min = Math.min(Infinity, ...results.values());
console.log(name);
for (const [type, result] of results) {
console.log(
` - ${type}: ${result}ms (${Math.round((result / min) * 10000) / 100}%)`
);
}
}

View File

@@ -1,70 +0,0 @@
#!/usr/bin/env node
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
require(`./tools`);
const fs = require(`fs`);
const vm = require(`vm`);
const WARMUP_ITERATIONS = 3;
const BENCHMARK_ITERATIONS = 10;
const testFiles = process.argv.slice(2).map((file) => {
return fs.readFileSync(file).toString();
});
const testResults = new Map();
for (const type of ["asmjs", "wasm"]) {
for (const file of testFiles) {
vm.runInNewContext(
file,
Object.assign(Object.create(global), {
Yoga: require(type === "asmjs"
? "../dist/entrypoint/asmjs-sync"
: "../dist/entrypoint/wasm-sync"),
YGBENCHMARK: function (name, fn) {
let testEntry = testResults.get(name);
if (testEntry === undefined)
testResults.set(name, (testEntry = new Map()));
for (let t = 0; t < WARMUP_ITERATIONS; ++t) fn();
const start = Date.now();
for (let t = 0; t < BENCHMARK_ITERATIONS; ++t) fn();
const end = Date.now();
testEntry.set(type, (end - start) / BENCHMARK_ITERATIONS);
},
})
);
}
}
console.log(
`Note: those tests are independants; there is no time relation to be expected between them`
);
for (const [name, results] of testResults) {
console.log();
const min = Math.min(Infinity, ...results.values());
console.log(name);
for (const [type, result] of results) {
console.log(
` - ${type}: ${result}ms (${Math.round((result / min) * 10000) / 100}%)`
);
}
}

View File

@@ -7,7 +7,19 @@
* @format
*/
global.getMeasureCounter = function (Yoga, cb, staticWidth, staticHeight) {
import type { MeasureFunction } from "yoga-layout";
import { Yoga } from "./globals";
export type MeasureCounter = {
inc: MeasureFunction;
get: () => number;
};
export function getMeasureCounter(
cb?: MeasureFunction | null,
staticWidth = 0,
staticHeight = 0
): MeasureCounter {
let counter = 0;
return {
@@ -23,10 +35,10 @@ global.getMeasureCounter = function (Yoga, cb, staticWidth, staticHeight) {
return counter;
},
};
};
}
global.getMeasureCounterMax = function (Yoga) {
return getMeasureCounter(Yoga, (width, widthMode, height, heightMode) => {
export function getMeasureCounterMax(): MeasureCounter {
return getMeasureCounter((width, widthMode, height, heightMode) => {
const measuredWidth =
widthMode === Yoga.MEASURE_MODE_UNDEFINED ? 10 : width;
const measuredHeight =
@@ -34,10 +46,10 @@ global.getMeasureCounterMax = function (Yoga) {
return { width: measuredWidth, height: measuredHeight };
});
};
}
global.getMeasureCounterMin = function (Yoga) {
return getMeasureCounter(Yoga, (width, widthMode, height, heightMode) => {
export function getMeasureCounterMin(): MeasureCounter {
return getMeasureCounter((width, widthMode, height, heightMode) => {
const measuredWidth =
widthMode === Yoga.MEASURE_MODE_UNDEFINED ||
(widthMode == Yoga.MEASURE_MODE_AT_MOST && width > 10)
@@ -51,4 +63,4 @@ global.getMeasureCounterMin = function (Yoga) {
return { width: measuredWidth, height: measuredHeight };
});
};
}

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { Yoga } from "yoga-layout";
declare global {
// eslint-disable-next-line no-var
var Yoga: Yoga | undefined;
// eslint-disable-next-line no-var
var YGBENCHMARK: (title: string, fn: () => void) => void;
}
if (globalThis.Yoga === undefined) {
throw new Error('Expected "Yoga" global to be set');
}
if (globalThis.YGBENCHMARK === undefined) {
throw new Error('Expected "YGBENCHMARK" global to be set');
}
const yoga = globalThis.Yoga;
const benchmark = globalThis.YGBENCHMARK;
export { yoga as Yoga, benchmark as YGBENCHMARK };