Add JavaScript bindings and WASM support
Co-authored-by: Matija Kecman <matijak@google.com> Co-authored-by: Sebastian Noreña Rendón <sebas.norena@creativa77.com.ar> Co-authored-by: Kyle Bayes <kylebayes@google.com> PiperOrigin-RevId: 826109484 Change-Id: I327fd54122762bd2e239cc31c602a3eb73051c26
This commit is contained in:
committed by
Copybara-Service
parent
76e64d96bb
commit
f2badc05ac
@@ -1,113 +0,0 @@
|
||||
// Copyright 2025 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import 'jasmine';
|
||||
|
||||
import { MainModule, DoubleBuffer } from "../dist/mujoco_wasm_benchmark"
|
||||
import loadMujoco from "../dist/mujoco_wasm_benchmark.js"
|
||||
|
||||
describe('MuJoCo WASM Benchmark Tests', () => {
|
||||
let mujoco: MainModule;
|
||||
|
||||
function isNumberArraySorted(arr: number[]): boolean {
|
||||
for (let i = 0; i < arr.length - 1; i++) {
|
||||
if (arr[i] > arr[i + 1]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function verifySorted(state: any, kind: string): void {
|
||||
let array: number[] = [];
|
||||
if (kind === 'NumberArray') {
|
||||
array = state as number[];
|
||||
} else {
|
||||
const bufferView = (state as DoubleBuffer).GetView();
|
||||
array = Array.from(bufferView) as number[];
|
||||
}
|
||||
|
||||
const sorted = isNumberArraySorted(array);
|
||||
if (!sorted) {
|
||||
console.error(` Verification failed for ${kind}. Array was ${array}`);
|
||||
}
|
||||
}
|
||||
|
||||
function runBenchmark(iterations: number, items: number, kind: string) {
|
||||
let state: any;
|
||||
let func: (state: any) => any;
|
||||
if (kind === 'NumberArray') {
|
||||
state = new Array(items).map(() => Math.random())
|
||||
func = (state) => mujoco.SortNumberArray(state);
|
||||
} else if (kind === 'DoubleBuffer') {
|
||||
state = mujoco.DoubleBuffer.FromArray(
|
||||
new Array(items).map(() => Math.random()));
|
||||
func = (state) => mujoco.SortDoubleBuffer(state);
|
||||
} else {
|
||||
throw new Error(`Unsupported benchmark type: ${kind}`);
|
||||
}
|
||||
|
||||
// Warmup JIT compiler to get stable results
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const sortedState = func(state);
|
||||
verifySorted(sortedState, kind);
|
||||
}
|
||||
|
||||
// Measurement
|
||||
const totalStartTime = performance.now();
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
func(state);
|
||||
}
|
||||
const totalEndTime = performance.now();
|
||||
|
||||
if (kind === 'DoubleBuffer') {
|
||||
state.delete();
|
||||
}
|
||||
|
||||
// Report results
|
||||
const totalTime = totalEndTime - totalStartTime;
|
||||
const avgTimeMilliseconds = totalTime / iterations;
|
||||
console.log(`Benchmark: "Sort ${kind} ${iterations} iterations with ${
|
||||
items} items" - AVG time per call: ${
|
||||
avgTimeMilliseconds.toFixed(2)} ms`);
|
||||
return {
|
||||
totalTime, avgTimeMilliseconds,
|
||||
}
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
mujoco = await loadMujoco();
|
||||
});
|
||||
|
||||
it('should benchmark NumberArray and DoubleBuffer and compare results',
|
||||
() => {
|
||||
const na1 = runBenchmark(100, 1_000, 'NumberArray');
|
||||
const na2 = runBenchmark(100, 400_000, 'NumberArray');
|
||||
|
||||
const db1 = runBenchmark(100, 1_000, 'DoubleBuffer');
|
||||
const db2 = runBenchmark(100, 400_000, 'DoubleBuffer');
|
||||
|
||||
// The actual time should be much faster than that but the intention of
|
||||
// the check is to catch huge regressions without a flakey test
|
||||
const _100ms = 100;
|
||||
|
||||
expect(db2.avgTimeMilliseconds).toBeLessThan(_100ms);
|
||||
|
||||
expect(db1.totalTime).toBeLessThan(na1.totalTime);
|
||||
expect(db2.totalTime).toBeLessThan(na2.totalTime);
|
||||
|
||||
expect(db1.avgTimeMilliseconds).toBeLessThan(na1.avgTimeMilliseconds);
|
||||
expect(db2.avgTimeMilliseconds).toBeLessThan(na2.avgTimeMilliseconds);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user