Last active
February 5, 2021 05:03
-
-
Save mendes5/43d1252142dae0e4339848608d8b7128 to your computer and use it in GitHub Desktop.
V8 vs Deno Call Overhead Test
This file contains hidden or 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
| fn add( | |
| scope: &mut v8::HandleScope, | |
| args: v8::FunctionCallbackArguments, | |
| mut rv: v8::ReturnValue, | |
| ) { | |
| let first = match v8::Local::<v8::Number>::try_from(args.get(0)) { | |
| Ok(s) => s.value(), | |
| Err(_) => { | |
| let msg = v8::String::new(scope, "Invalid argument").unwrap(); | |
| let exception = v8::Exception::type_error(scope, msg); | |
| scope.throw_exception(exception); | |
| return; | |
| } | |
| }; | |
| let second = match v8::Local::<v8::Number>::try_from(args.get(1)) { | |
| Ok(s) => s.value(), | |
| Err(_) => { | |
| let msg = v8::String::new(scope, "Invalid argument").unwrap(); | |
| let exception = v8::Exception::type_error(scope, msg); | |
| scope.throw_exception(exception); | |
| return; | |
| } | |
| }; | |
| let result = v8::Number::new(scope, first + second); | |
| rv.set(result.into()) | |
| } | |
| // Then at: core/bindings.rs:151 | |
| let add_key = v8::String::new(scope, "add").unwrap(); | |
| let add_tmpl = v8::FunctionTemplate::new(scope, add); | |
| let add_val = add_tmpl.get_function(scope).unwrap(); | |
| core_val.set(scope, add_key.into(), add_val.into()); |
This file contains hidden or 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
| use deno_core::json_op_sync; | |
| use deno_core::JsRuntime; | |
| use deno_core::ModuleSpecifier; | |
| use deno_core::Op; | |
| use deno_core::RuntimeOptions; | |
| use futures; | |
| use std::io::Write; | |
| use std::path::Path; | |
| fn main() { | |
| // Create the runtime | |
| let mut runtime = JsRuntime::new(RuntimeOptions { | |
| module_loader: Some(std::rc::Rc::new(deno_core::FsModuleLoader)), | |
| ..Default::default() | |
| }); | |
| // Register our add op using the deno api | |
| runtime.register_op( | |
| "op_add", | |
| json_op_sync(|_state, json, _| { | |
| let args: [f64; 2] = serde_json::from_value(json)?; | |
| Ok(serde_json::Value::from(args[0] + args[1])) | |
| }), | |
| ); | |
| // print function | |
| runtime.register_op( | |
| "op_print", | |
| |_state, zero_copy| { | |
| let mut out = std::io::stdout(); | |
| for buf in zero_copy { | |
| out.write_all(&buf).unwrap(); | |
| } | |
| Op::Sync(Box::new([])) | |
| }, | |
| ); | |
| // Read module | |
| let js_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("index.js"); | |
| let main_module = ModuleSpecifier::resolve_url_or_path(&js_path.to_string_lossy()).expect("Bah"); | |
| let mod_id = futures::executor::block_on(runtime.load_module(&main_module, None)).expect("Failed to load"); | |
| // Execute | |
| futures::executor::block_on(runtime.mod_evaluate(mod_id)).unwrap(); | |
| } |
This file contains hidden or 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
| // Ops = How many times the engine can call the function `add(x, y)` in 10 seconds | |
| // Using: taskset 0x00000001 | |
| // First Run | |
| [CoreJS] Ops 226.143.248 | |
| [WebAssembly] Ops 150.738.804 | |
| [V8 API] Ops 104.212.510 | |
| [DenoDispatch] Ops 3.305.002 | |
| // Second Run | |
| [CoreJS] Ops 223.669.638 | |
| [WebAssembly] Ops 145.839.616 | |
| [V8 API] Ops 102.851.270 | |
| [DenoDispatch] Ops 3.229.429 | |
| // Third Run | |
| [CoreJS] Ops 224.698.617 | |
| [WebAssembly] Ops 153.185.228 | |
| [V8 API] Ops 103.629.759 | |
| [DenoDispatch] Ops 3.230.980 |
This file contains hidden or 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
| Deno.core.ops(); | |
| function print(value) { | |
| Deno.core.dispatchByName('op_print', Deno.core.encode(value.toString()), new Uint8Array([10])); | |
| } | |
| { | |
| // Baseline JS add function, probably has zero call | |
| // overhead as it is probably inlined | |
| const add = (a, b) => a + b; | |
| let reduced = 0; | |
| let ops = 0; | |
| const start = Date.now(); | |
| while (Date.now() - start < 10000) { | |
| reduced += add(1,1); | |
| ops++; | |
| } | |
| const end = Date.now(); | |
| print("\n\n[CoreJS] Runtime " + (end - start)); | |
| print("[CoreJS] Result " + reduced); | |
| print("[CoreJS] Ops " + ops); | |
| } | |
| { | |
| let reduced = 0; | |
| let ops = 0; | |
| const start = Date.now(); | |
| // Webassembly module to add 2 numbers | |
| const bytes = new Uint8Array([ | |
| 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, | |
| 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, | |
| 0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01, | |
| 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b | |
| ]); | |
| const module = new WebAssembly.Module(bytes); | |
| const instance = new WebAssembly.Instance(module); | |
| while (Date.now() - start < 10000) { | |
| reduced += instance.exports.add(3, 4); | |
| ops++; | |
| } | |
| const end = Date.now(); | |
| print("\n\n[WebAssembly] Runtime " + (end - start)); | |
| print("[WebAssembly] Result " + reduced); | |
| print("[WebAssembly] Ops " + ops); | |
| } | |
| { | |
| let reduced = 0; | |
| let ops = 0; | |
| const start = Date.now(); | |
| while (Date.now() - start < 10000) { | |
| // Uses the function registered using the v8 API | |
| reduced += Deno.core.add(1,1); | |
| ops++; | |
| } | |
| const end = Date.now(); | |
| print("\n\n[V8 API] Runtime " + (end - start)); | |
| print("[V8 API] Result " + reduced); | |
| print("[V8 API] Ops " + ops); | |
| } | |
| { | |
| let reduced = 0; | |
| let ops = 0; | |
| const start = Date.now(); | |
| while (Date.now() - start < 10000) { | |
| // Adds using the Deno ops api | |
| reduced += JSON.parse(Deno.core.decode(Deno.core.dispatchByName('op_add', Deno.core.encode(JSON.stringify([1, 1]))))).ok; | |
| ops++; | |
| } | |
| const end = Date.now(); | |
| print("\n\n[DenoDispatch] Runtime " + (end - start)); | |
| print("[DenoDispatch] Result " + reduced); | |
| print("[DenoDispatch] Ops " + ops); | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment