-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[wasm] Add AppStart task to the bench Sample (#61481)
Measure browser app start times, 2 measurements implemented. First to measure till the JS window.pageshow event, second to measure time when we reach managed C# code. Example ouput: | measurement | time | |-:|-:| | AppStart, Page show | 108.1400ms | | AppStart, Reach managed | 240.2174ms |
- Loading branch information
1 parent
5fa6dd3
commit 35704e4
Showing
9 changed files
with
212 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Reflection; | ||
using System.Runtime.CompilerServices; | ||
using System.Text.Json; | ||
using System.Threading.Tasks; | ||
|
||
namespace Sample | ||
{ | ||
public class AppStartTask : BenchTask | ||
{ | ||
public override string Name => "AppStart"; | ||
public override bool BrowserOnly => true; | ||
|
||
[DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicConstructors, "System.Runtime.InteropServices.JavaScript.Runtime", "System.Private.Runtime.InteropServices.JavaScript")] | ||
static Type jsRuntimeType = System.Type.GetType("System.Runtime.InteropServices.JavaScript.Runtime, System.Private.Runtime.InteropServices.JavaScript", true); | ||
static Type jsFunctionType = System.Type.GetType("System.Runtime.InteropServices.JavaScript.Function, System.Private.Runtime.InteropServices.JavaScript", true); | ||
[DynamicDependency("InvokeJS(System.String)", "System.Runtime.InteropServices.JavaScript.Runtime", "System.Private.Runtime.InteropServices.JavaScript")] | ||
static MethodInfo invokeJSMethod = jsRuntimeType.GetMethod("InvokeJS", new Type[] { typeof(string) }); | ||
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, "System.Runtime.InteropServices.JavaScript.Function", "System.Private.Runtime.InteropServices.JavaScript")] | ||
static ConstructorInfo functionConstructor = jsRuntimeType.GetConstructor(new Type[] { typeof(object[]) }); | ||
[DynamicDependency("Call()", "System.Runtime.InteropServices.JavaScript.Function", "System.Private.Runtime.InteropServices.JavaScript")] | ||
static MethodInfo functionCall = jsFunctionType.GetMethod("Call", BindingFlags.Instance | BindingFlags.Public, new Type[] { }); | ||
|
||
public AppStartTask() | ||
{ | ||
measurements = new Measurement[] { | ||
new PageShow(), | ||
new ReachManaged(), | ||
}; | ||
} | ||
|
||
Measurement[] measurements; | ||
public override Measurement[] Measurements => measurements; | ||
|
||
static string InvokeJS(string js) | ||
{ | ||
return (string)invokeJSMethod.Invoke(null, new object[] { js }); | ||
} | ||
|
||
class PageShow : BenchTask.Measurement | ||
{ | ||
public override string Name => "Page show"; | ||
|
||
public override int InitialSamples => 3; | ||
|
||
async Task RunAsyncStep() | ||
{ | ||
var function = Activator.CreateInstance(jsFunctionType, new object[] { new object[] { @"return App.StartAppUI();" } }); | ||
var task = (Task<object>)functionCall.Invoke(function, new object[] { }); | ||
|
||
await task; | ||
} | ||
|
||
public override bool HasRunStepAsync => true; | ||
|
||
public override async Task RunStepAsync() | ||
{ | ||
var function = Activator.CreateInstance(jsFunctionType, new object[] { new object[] { @"return App.PageShow();" } }); | ||
await (Task<object>)functionCall.Invoke(function, null); | ||
} | ||
} | ||
|
||
class ReachManaged : BenchTask.Measurement | ||
{ | ||
public override string Name => "Reach managed"; | ||
public override int InitialSamples => 3; | ||
public override bool HasRunStepAsync => true; | ||
|
||
static object jsUIReachedManagedFunction = Activator.CreateInstance(jsFunctionType, new object[] { new object[] { @"return App.ReachedManaged();" } }); | ||
static object jsReached = Activator.CreateInstance(jsFunctionType, new object[] { new object[] { @"return App.reached();" } }); | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
public static void Reached() | ||
{ | ||
functionCall.Invoke(jsReached, null); | ||
} | ||
|
||
public override async Task RunStepAsync() | ||
{ | ||
await (Task<object>)functionCall.Invoke(jsUIReachedManagedFunction, null); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<!DOCTYPE html> | ||
<!-- Licensed to the .NET Foundation under one or more agreements. --> | ||
<!-- The .NET Foundation licenses this file to you under the MIT license. --> | ||
<html> | ||
<head> | ||
<title>App task</title> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
</head> | ||
<body> | ||
<h3 id="header">Wasm Browser Sample - App task frame</h3> | ||
<span id="out"></span> | ||
<script type='text/javascript'> | ||
var test_exit = function(exit_code) | ||
{ | ||
/* Set result in a tests_done element, to be read by xharness */ | ||
var tests_done_elem = document.createElement("label"); | ||
tests_done_elem.id = "tests_done"; | ||
tests_done_elem.innerHTML = exit_code.toString(); | ||
document.body.appendChild(tests_done_elem); | ||
|
||
console.log(`WASM EXIT ${exit_code}`); | ||
}; | ||
|
||
window.addEventListener("pageshow", event => { window.parent.resolveAppStartEvent(event); }) | ||
|
||
var App = { | ||
init: function () { | ||
INTERNAL.call_static_method("[Wasm.Browser.Bench.Sample] Sample.AppStartTask/ReachManaged:Reached"); | ||
}, | ||
|
||
reached: function() { | ||
window.parent.resolveAppStartEvent("reached"); | ||
} | ||
}; | ||
|
||
</script> | ||
<script type="text/javascript" src="runtime.js"></script> | ||
<script defer src="dotnet.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
var AppStart = { | ||
Construct: function() { | ||
this._frame = document.createElement('iframe'); | ||
document.body.appendChild(this._frame); | ||
}, | ||
|
||
WaitForPageShow: async function() { | ||
let promise; | ||
let promiseResolve; | ||
this._frame.src = 'appstart-frame.html'; | ||
promise = new Promise(resolve => { promiseResolve = resolve; }) | ||
window.resolveAppStartEvent = function(event) { promiseResolve(); } | ||
await promise; | ||
}, | ||
|
||
WaitForReached: async function() { | ||
let promise; | ||
let promiseResolve; | ||
this._frame.src = 'appstart-frame.html'; | ||
promise = new Promise(resolve => { promiseResolve = resolve; }) | ||
window.resolveAppStartEvent = function(event) { | ||
if (event == "reached") | ||
promiseResolve(); | ||
} | ||
await promise; | ||
}, | ||
|
||
RemoveFrame: function () { | ||
document.body.removeChild(this._frame); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
iframe { | ||
display:none; | ||
} |