Browse Source
- Updated the README.md with the description of benchmarks (might be useful to external parties) - customized a runner for D8 - added a `warmupCount` parameter to `runBenchmarks`, because it's required for Jetstream3 (a set of benchmarks) that there is no warmup (they skip it) - Added a smooth scroll variant of LazyGrid + variants with LaunchedEffect in grid cells for coroutines usage. - Added a new class `Config`. Object `Args` is simplified, it's purpose is to simply parse the arguments and produce a instance of `Config`. The usages of `Args` were replaced by `Config`, except the parsing in fun main. - Renamed Example1 to MultipleComponents - Also added MultipleComponents-NoVectorGraphics for D8 - it's similar to MultipleComponents but doesn't use vector icons. Fixes https://youtrack.jetbrains.com/issue/CMP-6942 Note: it's based on this PR https://github.com/JetBrains/compose-multiplatform/pull/5275 ## Testing Manually run the benchmarks ## Release Notes N/Apull/5302/head
18 changed files with 454 additions and 151 deletions
|
After Width: | Height: | Size: 34 KiB |
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="600dp" |
||||
android:height="600dp" |
||||
android:viewportWidth="600" |
||||
android:viewportHeight="600"> |
||||
<path |
||||
android:pathData="M301.21,418.53C300.97,418.54 300.73,418.56 300.49,418.56C297.09,418.59 293.74,417.72 290.79,416.05L222.6,377.54C220.63,376.43 219,374.82 217.85,372.88C216.7,370.94 216.09,368.73 216.07,366.47L216.07,288.16C216.06,287.32 216.09,286.49 216.17,285.67C216.38,283.54 216.91,281.5 217.71,279.6L199.29,268.27L177.74,256.19C175.72,260.43 174.73,265.23 174.78,270.22L174.79,387.05C174.85,393.89 178.57,400.2 184.53,403.56L286.26,461.02C290.67,463.51 295.66,464.8 300.73,464.76C300.91,464.76 301.09,464.74 301.27,464.74C301.24,449.84 301.22,439.23 301.22,439.23L301.21,418.53Z" |
||||
android:fillColor="#041619" |
||||
android:fillType="nonZero"/> |
||||
<path |
||||
android:pathData="M409.45,242.91L312.64,188.23C303.64,183.15 292.58,183.26 283.68,188.51L187.92,245C183.31,247.73 179.93,251.62 177.75,256.17L177.74,256.19L199.29,268.27L217.71,279.6C217.83,279.32 217.92,279.02 218.05,278.74C218.24,278.36 218.43,277.98 218.64,277.62C219.06,276.88 219.52,276.18 220.04,275.51C221.37,273.8 223.01,272.35 224.87,271.25L289.06,233.39C290.42,232.59 291.87,231.96 293.39,231.51C295.53,230.87 297.77,230.6 300,230.72C302.98,230.88 305.88,231.73 308.47,233.2L373.37,269.85C375.54,271.08 377.49,272.68 379.13,274.57C379.68,275.19 380.18,275.85 380.65,276.53C380.86,276.84 381.05,277.15 381.24,277.47L397.79,266.39L420.34,252.93L420.31,252.88C417.55,248.8 413.77,245.35 409.45,242.91Z" |
||||
android:fillColor="#37BF6E" |
||||
android:fillType="nonZero"/> |
||||
<path |
||||
android:pathData="M381.24,277.47C381.51,277.92 381.77,278.38 382.01,278.84C382.21,279.24 382.39,279.65 382.57,280.06C382.91,280.88 383.19,281.73 383.41,282.59C383.74,283.88 383.92,285.21 383.93,286.57L383.93,361.1C383.96,363.95 383.35,366.77 382.16,369.36C381.93,369.86 381.69,370.35 381.42,370.83C379.75,373.79 377.32,376.27 374.39,378L310.2,415.87C307.47,417.48 304.38,418.39 301.21,418.53L301.22,439.23C301.22,439.23 301.24,449.84 301.27,464.74C306.1,464.61 310.91,463.3 315.21,460.75L410.98,404.25C419.88,399 425.31,389.37 425.22,379.03L425.22,267.85C425.17,262.48 423.34,257.34 420.34,252.93L397.79,266.39L381.24,277.47Z" |
||||
android:fillColor="#3870B2" |
||||
android:fillType="nonZero"/> |
||||
<path |
||||
android:pathData="M177.75,256.17C179.93,251.62 183.31,247.73 187.92,245L283.68,188.51C292.58,183.26 303.64,183.15 312.64,188.23L409.45,242.91C413.77,245.35 417.55,248.8 420.31,252.88L420.34,252.93L498.59,206.19C494.03,199.46 487.79,193.78 480.67,189.75L320.86,99.49C306.01,91.1 287.75,91.27 273.07,99.95L114.99,193.2C107.39,197.69 101.81,204.11 98.21,211.63L177.74,256.19L177.75,256.17ZM301.27,464.74C301.09,464.74 300.91,464.76 300.73,464.76C295.66,464.8 290.67,463.51 286.26,461.02L184.53,403.56C178.57,400.2 174.85,393.89 174.79,387.05L174.78,270.22C174.73,265.23 175.72,260.43 177.74,256.19L98.21,211.63C94.86,218.63 93.23,226.58 93.31,234.82L93.31,427.67C93.42,438.97 99.54,449.37 109.4,454.92L277.31,549.77C284.6,553.88 292.84,556.01 301.2,555.94L301.2,555.8C301.39,543.78 301.33,495.26 301.27,464.74Z" |
||||
android:strokeWidth="10" |
||||
android:fillColor="#00000000" |
||||
android:strokeColor="#083042" |
||||
android:fillType="nonZero"/> |
||||
<path |
||||
android:pathData="M498.59,206.19L420.34,252.93C423.34,257.34 425.17,262.48 425.22,267.85L425.22,379.03C425.31,389.37 419.88,399 410.98,404.25L315.21,460.75C310.91,463.3 306.1,464.61 301.27,464.74C301.33,495.26 301.39,543.78 301.2,555.8L301.2,555.94C309.48,555.87 317.74,553.68 325.11,549.32L483.18,456.06C497.87,447.39 506.85,431.49 506.69,414.43L506.69,230.91C506.6,222.02 503.57,213.5 498.59,206.19Z" |
||||
android:strokeWidth="10" |
||||
android:fillColor="#00000000" |
||||
android:strokeColor="#083042" |
||||
android:fillType="nonZero"/> |
||||
<path |
||||
android:pathData="M301.2,555.94C292.84,556.01 284.6,553.88 277.31,549.76L109.4,454.92C99.54,449.37 93.42,438.97 93.31,427.67L93.31,234.82C93.23,226.58 94.86,218.63 98.21,211.63C101.81,204.11 107.39,197.69 114.99,193.2L273.07,99.95C287.75,91.27 306.01,91.1 320.86,99.49L480.67,189.75C487.79,193.78 494.03,199.46 498.59,206.19C503.57,213.5 506.6,222.02 506.69,230.91L506.69,414.43C506.85,431.49 497.87,447.39 483.18,456.06L325.11,549.32C317.74,553.68 309.48,555.87 301.2,555.94Z" |
||||
android:strokeWidth="10" |
||||
android:fillColor="#00000000" |
||||
android:strokeColor="#083042" |
||||
android:fillType="nonZero"/> |
||||
</vector> |
||||
@ -1,15 +1,81 @@
@@ -1,15 +1,81 @@
|
||||
@file:OptIn(ExperimentalJsExport::class) |
||||
|
||||
import kotlinx.browser.window |
||||
import kotlinx.coroutines.MainScope |
||||
import kotlinx.coroutines.launch |
||||
import kotlinx.coroutines.* |
||||
import org.w3c.dom.url.URLSearchParams |
||||
import kotlin.js.Promise |
||||
|
||||
val jsOne = 1.toJsNumber() |
||||
|
||||
fun main(args: Array<String>) { |
||||
if (isD8env().toBoolean()) { |
||||
mainD8(args) |
||||
} else { |
||||
mainBrowser() |
||||
} |
||||
} |
||||
|
||||
fun main() { |
||||
fun mainBrowser() { |
||||
val urlParams = URLSearchParams(window.location.search.toJsString()) |
||||
var i = 0 |
||||
val args = generateSequence { urlParams.get("arg${i++}") }.toList().toTypedArray() |
||||
Args.parseArgs(args) |
||||
|
||||
Config.setGlobalFromArgs(args) |
||||
|
||||
MainScope().launch { |
||||
runBenchmarks() |
||||
println("Completed!") |
||||
} |
||||
} |
||||
|
||||
|
||||
// Currently, the initialization can't be adjusted to avoid calling the fun main, but |
||||
// we don't want use the default fun main, because Jetstream3 requires running the workloads separately / independently of each other. |
||||
// Also, they require that a benchmark completes before the function exists, which is not possible with if they just call fun main. |
||||
// Therefore, they'll rely on fun customLaunch, which returns a Promise (can be awaited for). |
||||
fun mainD8(args: Array<String>) { |
||||
println("mainD8 is intentionally doing nothing. Read the comments in main.wasmJs.kt") |
||||
} |
||||
|
||||
private val basicConfigForD8 = Config( |
||||
// Using only SIMPLE mode, because VSYNC_EMULATION calls delay(...), |
||||
// which is implemented via setTimeout on web targets. |
||||
// setTimeout implementation is simplified in D8, making |
||||
// the VSYNC_EMULATION mode meaningless when running in D8 |
||||
modes = setOf(Mode.SIMPLE), |
||||
// MultipleComponents is unsupported, because it uses vector icons. D8 doesn't provide XML parsing APIs. |
||||
// But there is an alternative workload called 'MultipleComponents-NoVectorGraphics' |
||||
disabledBenchmarks = setOf("MultipleComponents"), |
||||
) |
||||
|
||||
@JsExport |
||||
fun customLaunch(benchmarkName: String, frameCount: Int): Promise<JsAny?> { |
||||
val config = basicConfigForD8.copy( |
||||
benchmarks = mapOf(benchmarkName to frameCount) |
||||
) |
||||
Config.setGlobal(config) |
||||
|
||||
return MainScope().promise { |
||||
runBenchmarks(warmupCount = 0) |
||||
jsOne |
||||
} |
||||
} |
||||
|
||||
@JsExport |
||||
fun d8BenchmarksRunner(args: String): Promise<JsAny?> { |
||||
val config = Args.parseArgs(args.split(" ").toTypedArray()) |
||||
.copy( |
||||
modes = basicConfigForD8.modes, |
||||
disabledBenchmarks = basicConfigForD8.disabledBenchmarks |
||||
) |
||||
|
||||
Config.setGlobal(config) |
||||
|
||||
return MainScope().promise { |
||||
runBenchmarks() |
||||
jsOne |
||||
} |
||||
} |
||||
|
||||
private fun isD8env(): JsBoolean = |
||||
js("typeof isD8 !== 'undefined'") |
||||
|
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
globalThis.isD8 = true; |
||||
|
||||
import * as skiko from './skikod8.mjs'; |
||||
import { instantiate } from './compose-benchmarks-benchmarks-wasm-js.uninstantiated.mjs'; |
||||
|
||||
const exports = (await instantiate({ |
||||
'./skiko.mjs': skiko |
||||
})).exports; |
||||
|
||||
await import('./polyfills.mjs'); |
||||
|
||||
await exports.d8BenchmarksRunner(Array.from(arguments).join(' ')); |
||||
console.log('Finished'); |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
globalThis.isD8 = true; |
||||
|
||||
import * as skiko from './skikod8.mjs'; |
||||
import { instantiate } from './compose-benchmarks-benchmarks-wasm-js.uninstantiated.mjs'; |
||||
|
||||
const exports = (await instantiate({ |
||||
'./skiko.mjs': skiko |
||||
})).exports; |
||||
|
||||
await import('./polyfills.mjs'); |
||||
|
||||
/* |
||||
AnimatedVisibility, |
||||
LazyGrid, |
||||
LazyGrid-ItemLaunchedEffect, |
||||
LazyGrid-SmoothScroll, |
||||
LazyGrid-SmoothScroll-ItemLaunchedEffect, |
||||
VisualEffects, |
||||
MultipleComponents-NoVectorGraphics |
||||
*/ |
||||
let name = arguments[0] ? arguments[0] : 'AnimatedVisibility'; |
||||
let frameCount = arguments[1] ? parseInt(arguments[1]) : 1000; |
||||
await exports.customLaunch(name, frameCount); |
||||
console.log('Finished'); |
||||
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
// polyfills.mjs
|
||||
if (typeof globalThis.window === 'undefined') { |
||||
globalThis.window = globalThis; |
||||
} |
||||
if (typeof globalThis.navigator === 'undefined') { |
||||
globalThis.navigator = {}; |
||||
} |
||||
if (!globalThis.navigator.languages) { |
||||
globalThis.navigator.languages = ['en-US', 'en']; |
||||
globalThis.navigator.userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'; |
||||
globalThis.navigator.platform = "MacIntel"; |
||||
} |
||||
|
||||
if (!globalThis.gc) { |
||||
// No GC control in D8
|
||||
globalThis.gc = () => { |
||||
// console.log('gc called');
|
||||
}; |
||||
} |
||||
|
||||
// Minimal Blob polyfill
|
||||
class BlobPolyfill { |
||||
constructor(uint8, type = '') { |
||||
this._uint8 = uint8; |
||||
this._type = type; |
||||
} |
||||
get size() { |
||||
return this._uint8.byteLength; |
||||
} |
||||
get type() { return this._type; } |
||||
async arrayBuffer() { |
||||
console.log('arrayBuffer called'); |
||||
return this._uint8.buffer; |
||||
} |
||||
} |
||||
|
||||
globalThis.fetch = async (p) => { |
||||
let data; |
||||
try { |
||||
let path = p.replace(/^\.\//, ''); |
||||
console.log('fetch', path); |
||||
data = read(path, 'binary'); |
||||
} catch (err) { |
||||
console.log('error', err); |
||||
} |
||||
|
||||
const uint8 = new Uint8Array(data); |
||||
|
||||
return { |
||||
ok: true, |
||||
status: 200, |
||||
async blob() { |
||||
return new BlobPolyfill(uint8, 'application/xml'); |
||||
}, |
||||
}; |
||||
}; |
||||
Loading…
Reference in new issue