-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A new low-level crate with focus on speed. This doesn't yet hook into the existing code base.
- Loading branch information
Showing
26 changed files
with
1,478 additions
and
120 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
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,37 @@ | ||
import("//build_extra/rust/rust.gni") | ||
|
||
# deno_core does not depend on flatbuffers nor tokio. | ||
main_extern = [ | ||
"$rust_build:futures", | ||
"$rust_build:libc", | ||
"$rust_build:serde_json", | ||
"$rust_build:log", | ||
] | ||
|
||
rust_crate("deno_core") { | ||
source_root = "lib.rs" | ||
extern = main_extern | ||
deps = [ | ||
"../libdeno:libdeno_static_lib", | ||
] | ||
} | ||
|
||
rust_test("deno_core_test") { | ||
source_root = "lib.rs" | ||
extern = main_extern | ||
deps = [ | ||
"../libdeno:libdeno_static_lib", | ||
] | ||
} | ||
|
||
rust_executable("deno_core_http_bench") { | ||
source_root = "http_bench.rs" | ||
extern = [ | ||
"$rust_build:futures", | ||
"$rust_build:lazy_static", | ||
"$rust_build:libc", | ||
"$rust_build:log", | ||
"$rust_build:tokio", | ||
":deno_core" | ||
] | ||
} |
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,150 @@ | ||
// This is not a real HTTP server. We read blindly one time into 'requestBuf', | ||
// then write this fixed 'responseBuf'. The point of this benchmark is to | ||
// exercise the event loop in a simple yet semi-realistic way. | ||
const shared32 = new Int32Array(libdeno.shared); | ||
|
||
const INDEX_NUM_RECORDS = 0; | ||
const INDEX_RECORDS = 1; | ||
const RECORD_OFFSET_PROMISE_ID = 0; | ||
const RECORD_OFFSET_OP = 1; | ||
const RECORD_OFFSET_ARG = 2; | ||
const RECORD_OFFSET_RESULT = 3; | ||
const RECORD_SIZE = 4; | ||
const OP_LISTEN = 1; | ||
const OP_ACCEPT = 2; | ||
const OP_READ = 3; | ||
const OP_WRITE = 4; | ||
const OP_CLOSE = 5; | ||
|
||
const NUM_RECORDS = (shared32.length - INDEX_RECORDS) / RECORD_SIZE; | ||
if (NUM_RECORDS != 100) { | ||
throw Error("expected 100 entries"); | ||
} | ||
|
||
const requestBuf = new Uint8Array(64 * 1024); | ||
const responseBuf = new Uint8Array( | ||
"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n" | ||
.split("") | ||
.map(c => c.charCodeAt(0)) | ||
); | ||
|
||
const promiseMap = new Map(); | ||
let nextPromiseId = 1; | ||
|
||
function createResolvable() { | ||
let methods; | ||
const promise = new Promise((resolve, reject) => { | ||
methods = { resolve, reject }; | ||
}); | ||
return Object.assign(promise, methods); | ||
} | ||
|
||
/** Returns Promise<number> */ | ||
function sendAsync(op, arg, zeroCopyData) { | ||
const id = nextPromiseId++; | ||
const p = createResolvable(); | ||
shared32[INDEX_NUM_RECORDS] = 1; | ||
setRecord(0, RECORD_OFFSET_PROMISE_ID, id); | ||
setRecord(0, RECORD_OFFSET_OP, op); | ||
setRecord(0, RECORD_OFFSET_ARG, arg); | ||
setRecord(0, RECORD_OFFSET_RESULT, -1); | ||
promiseMap.set(id, p); | ||
libdeno.send(null, zeroCopyData); | ||
return p; | ||
} | ||
|
||
/** Returns u32 number */ | ||
function sendSync(op, arg) { | ||
shared32[INDEX_NUM_RECORDS] = 1; | ||
setRecord(0, RECORD_OFFSET_PROMISE_ID, 0); | ||
setRecord(0, RECORD_OFFSET_OP, op); | ||
setRecord(0, RECORD_OFFSET_ARG, arg); | ||
setRecord(0, RECORD_OFFSET_RESULT, -1); | ||
libdeno.send(); | ||
return getRecord(0, RECORD_OFFSET_RESULT); | ||
} | ||
|
||
function setRecord(i, off, value) { | ||
if (i >= NUM_RECORDS) { | ||
throw Error("out of range"); | ||
} | ||
shared32[INDEX_RECORDS + RECORD_SIZE * i + off] = value; | ||
} | ||
|
||
function getRecord(i, off) { | ||
if (i >= NUM_RECORDS) { | ||
throw Error("out of range"); | ||
} | ||
return shared32[INDEX_RECORDS + RECORD_SIZE * i + off]; | ||
} | ||
|
||
function handleAsyncMsgFromRust() { | ||
for (let i = 0; i < shared32[INDEX_NUM_RECORDS]; i++) { | ||
let id = getRecord(i, RECORD_OFFSET_PROMISE_ID); | ||
const p = promiseMap.get(id); | ||
promiseMap.delete(id); | ||
p.resolve(getRecord(i, RECORD_OFFSET_RESULT)); | ||
} | ||
} | ||
|
||
/** Listens on 0.0.0.0:4500, returns rid. */ | ||
function listen() { | ||
return sendSync(OP_LISTEN, -1); | ||
} | ||
|
||
/** Accepts a connection, returns rid. */ | ||
async function accept(rid) { | ||
return await sendAsync(OP_ACCEPT, rid); | ||
} | ||
|
||
/** | ||
* Reads a packet from the rid, presumably an http request. data is ignored. | ||
* Returns bytes read. | ||
*/ | ||
async function read(rid, data) { | ||
return await sendAsync(OP_READ, rid, data); | ||
} | ||
|
||
/** Writes a fixed HTTP response to the socket rid. Returns bytes written. */ | ||
async function write(rid, data) { | ||
return await sendAsync(OP_WRITE, rid, data); | ||
} | ||
|
||
function close(rid) { | ||
return sendSync(OP_CLOSE, rid); | ||
} | ||
|
||
async function serve(rid) { | ||
while (true) { | ||
const nread = await read(rid, requestBuf); | ||
if (nread <= 0) { | ||
break; | ||
} | ||
|
||
const nwritten = await write(rid, responseBuf); | ||
if (nwritten < 0) { | ||
break; | ||
} | ||
} | ||
close(rid); | ||
} | ||
|
||
async function main() { | ||
libdeno.recv(handleAsyncMsgFromRust); | ||
|
||
libdeno.print("http_bench.js start"); | ||
|
||
const listener_rid = listen(); | ||
libdeno.print(`listening http://127.0.0.1:4544/ rid = ${listener_rid}`); | ||
while (true) { | ||
const rid = await accept(listener_rid); | ||
// libdeno.print(`accepted ${rid}`); | ||
if (rid < 0) { | ||
libdeno.print(`accept error ${rid}`); | ||
return; | ||
} | ||
serve(rid); | ||
} | ||
} | ||
|
||
main(); |
Oops, something went wrong.