Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ bytes = "1.2.1"
serde_json = "1.0.85"
lazy_static = "1.4.0"
tokio = { version = "1", features = ["full"] }
actix-http = { version = "3.2", features = ["http2"]}
actix-service = "2.0.2"
futures = "0.3.24"
http = "0.2.8"
actix-rt = "2.7.0"
actix-server = "2.1.1"
tera = "1.17.1"
parking_lot = "0.12.1"
simdutf8 = "0.1.4"
halfbrown = "0.1.15"
tokio-postgres = { version = "0.7.7", features = ["with-serde_json-1" ] }
num_cpus = "1.13.1"
extreme = "666.666.666666"
rustls = "0.20.7"
rustls-pemfile = "1.0.1"
kanal = "0.1.0-pre7"
ntex = { version = "0.5.29", features = ["tokio", "rustls"] }

[target.'cfg(not(target_os = "linux"))'.dependencies]
mimalloc-rust = { version = "0.2" }
Expand Down
10 changes: 6 additions & 4 deletions __test__/saturation.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import * as Walker from '../index.js'

const config = {
url: "0.0.0.0:8080",
worker_threads: "1",
backlog: "1000000",
pool_per_worker_size: "1"
workerThreads: 1,
backlog: 1000000,
poolPerWorkerSize: 1,
debug: false,
tls: false,
}

test.serial.before(async (_) => {
Expand Down Expand Up @@ -46,4 +48,4 @@ test("Get /cpu 5_000 times", async t => {
responses.forEach((resp, index) => {
t.is(resp.data, `Param: ${index}`);
});
});
});
20 changes: 20 additions & 0 deletions __test__/worker_file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const Walker = require('..');
const response = "Hello World!"

Walker.get(`/`, (res) => {
res.sendTextUnchecked(response);
})

Walker.get(`/slowrunner/:count`, (res) => {
const params = res.getUrlParams();
const count = parseInt(params.count);
let i = 0;

for (; i < count; i++) {

}

res.sendTextUnchecked(`Result ${i}`)
})

Walker.registerThreadsPool(50_000);
93 changes: 93 additions & 0 deletions __test__/workers_test.spec.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import test from 'ava'
import axios from 'axios';
import { Worker } from 'node:worker_threads';
import { fileURLToPath } from 'url';
import path from 'path';

const Server = axios.create({
baseURL: 'http://0.0.0.0:8080/'
});

import * as Walker from '../index.js'

const config = {
url: "0.0.0.0:8080",
workerThreads: 8,
backlog: 500,
poolPerWorkerSize: 1_000,
debug: false,
tls: false,
}

test.serial.before(async (_) => {
let dir = path.dirname(fileURLToPath(import.meta.url));
for (let i = 0; i < 5; i++) {
const worker = new Worker(`${dir}/worker_file.js`);
}

// We'll let the worker threads spin up
await new Promise((resolve) => setTimeout(resolve, 1000));

Walker.startWithConfig(config);

// Sleeep for 100ms to let server start
await new Promise((resolve) => setTimeout(resolve, 300));
});

// Hit the cpu endpoint 5_000 times to saturate the object pool
test.serial("Get /slowrunner multiple times in waves", async t => {
const req_number = 100;
const loop_number = 100_000;

for (let c = 0; c < 100; c++) {
const promises = [];
for (let i = 0; i < req_number; i++) {
promises.push(Server.get(`/slowrunner/${loop_number}`));
}

const responses = await Promise.all(promises);

t.is(responses.length, req_number);
// check all the responses are correct
responses.forEach((resp, index) => {
t.is(resp.data, `Result ${loop_number}`);
});
}
});


// Hit the endpoint with a continious load
test.serial("Get /slowrunner multiple times with a consistent load", async t => {
const promises = [];
const req_number = 1000;
const loop_number = 100_000;
let sum_of_requests = 10_000;

for (let i = 0; i < req_number; i++) {
const p = Server.get(`/slowrunner/${loop_number}`).then(res => {
promises.splice(promises.indexOf(p), 1);
return res;
});
promises.push(p);
}

while (sum_of_requests > 0) {
const complete = await Promise.race(promises);
sum_of_requests -= 1;

const p = Server.get(`/slowrunner/${loop_number}`).then(res => {
promises.splice(promises.indexOf(p), 1);
return res;
});
promises.push(p);

t.is(complete.data, `Result ${loop_number}`);
}

const responses = await Promise.all(promises);

// check all the responses are correct
responses.forEach((resp, index) => {
t.is(resp.data, `Result ${loop_number}`);
});
});
25 changes: 25 additions & 0 deletions examples/certs/cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIEMzCCApugAwIBAgIQLDkJeN2TgRSdTqyim8Yq5zANBgkqhkiG9w0BAQsFADB1
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExJTAjBgNVBAsMHGphY2tA
amFja3MtcGMgKEphY2sgVGhvbXNvbikxLDAqBgNVBAMMI21rY2VydCBqYWNrQGph
Y2tzLXBjIChKYWNrIFRob21zb24pMB4XDTIyMTEwMjE3NDMwM1oXDTI1MDIwMjE3
NDMwM1owUDEnMCUGA1UEChMebWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRl
MSUwIwYDVQQLDBxqYWNrQGphY2tzLXBjIChKYWNrIFRob21zb24pMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5JX+pB8B/lCT40augS4isxU+ZX4bFC+d
9S8u2vnMv6cF9NtsVzGp9ZruVd6mF5qkAH0EWz0xVW8paPrJKE+8cMhLIRbwL+pt
Teljs8VNV/qxbQQQaXWFJw/tUSdhErMCKgp0XSy6WfS39+5L+gsl+hpda65w5DQs
bAxyVZ4cAUugNI2Va9eVnNfqGo88UzaFunY4pi0uXkJX8E+QdcNiizvslsBifjsp
iwewPBfRb6Fz7bXefL8Fa/dC42riLEKTibGU1ymEsKYET3Pmprg0VmCwQX+qNLG4
MsrxE4IYVlH+/BCVfakmkUi4MRZNBWXT0xZNmfORWSvDBgrt131gCQIDAQABo2Qw
YjAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHwYDVR0jBBgw
FoAU2hmilf5DgQ1mWcDUpd7Nu5S6wxQwGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/
AAABMA0GCSqGSIb3DQEBCwUAA4IBgQBtwVdwdq15K9IWOcoGNqFzy7S4iCBfOsEM
9/F7mPWD8t5QvvRFRFrCQkTBL74enfZ/BKEAXFxQCPT8dM6LgXQH435Pe/pHVExs
F3RzoPG/WGrPIxM7eW/BXT0z08wbeeMFbSQdy+dD2c5oMFkKGbYT9qkDv1Ic/p9Z
0QjqiytY3xLOdUh0JCvCw8QrS7+4M9/5U1Le0gxLmwvWgh8EE1B5fXfSgu3vyjfr
P4N6TMNiYdeNEQhMTc6rkL9vh1Il6Ue612Z/S44ttobKoanCnL79qjDYFMetSxlQ
YXp/qeHGGgG5c0kthlaPlnf4qKDs5hn3MblozO2zo7CqLu8YIcJ6zUi7GWdth2td
V3KjvUrDg6xkrAZY1HxebNDBN6lRYNefhvZojOUfZgJSX8Smxzwp3V3W4jZqBI1X
IMmsjSD7qQGMPkTjFqdZTsKtgQR3UA1etkuC5tiDoMRzdr+S/cyZRXhIlTAPxIot
5NB0MEezFhDFOVrzi2iuFgTBYAgou1E=
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions examples/certs/key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDklf6kHwH+UJPj
Rq6BLiKzFT5lfhsUL531Ly7a+cy/pwX022xXMan1mu5V3qYXmqQAfQRbPTFVbylo
+skoT7xwyEshFvAv6m1N6WOzxU1X+rFtBBBpdYUnD+1RJ2ESswIqCnRdLLpZ9Lf3
7kv6CyX6Gl1rrnDkNCxsDHJVnhwBS6A0jZVr15Wc1+oajzxTNoW6djimLS5eQlfw
T5B1w2KLO+yWwGJ+OymLB7A8F9FvoXPttd58vwVr90LjauIsQpOJsZTXKYSwpgRP
c+amuDRWYLBBf6o0sbgyyvETghhWUf78EJV9qSaRSLgxFk0FZdPTFk2Z85FZK8MG
Cu3XfWAJAgMBAAECggEBAIaLnzGdKsA1T4b0QJy6uiPsuihlHK06BeCeYBb198VL
G19vlAqSqfZttiGHBv5XwHalH15Q22vtHVO0YZi/riw4SLh2VvPtKV81o8DZvlet
sKd5P+vDB5fhcQ9WfXXTNc/nDW0Wea2fNHXTppbL3xOiVyCdsccwyoDipp2sjdFY
RAgcumRMFmkNh1V9xHM3N/mT5KD8kkhNmClMGag9BH6RSy/ur+93o2kTXatapdSI
ufRKIsE6ti1wX1buudNBXXfB7qHOKZOFyqsmqaDtX3Jg31VfzCQuQu4g1fXlqgZl
RkJlz/QzFo7fMqpyk7Fqg+9AaHh+68/HcJodrNG4gy0CgYEA/1pn1mJqAMgKUlDu
G/1magImqjQY2yUzCANV8cRywMtM8kuv14Xk6N/4IvYI2dai/D+ptgyHsJreUa/K
PQ1VkiyGrQLKVZb/ZIJe6Lv+Dhsi5IKwuDo15FHaLJP4snYOu8g1bpbDFf62iD8p
EttkwhBT7X96GEHgPzY5fDu3Ay8CgYEA5So7EoXZ5XgxNa5mRK0mg2ONHwOl4vf4
eSN6cJZQQxBjZTzX9irL5bRknoRW1O80Pu6FDaoiv8MBMSDYlBC4+/e73neixEuz
SQYL/ozSXqtQr199EyyKIN8yWR2yy+W49+hrW+1IW8ANVES9sIgHErEBK8u3rJXB
yWQYCSzU4kcCgYAUWbkizc8S5t5jtw1y75wE4M0CDYrZlDpf7hwgW36lvM4SFVQb
QhF/ObJF3wPPkJqGrfAxkQgTXBRRwEfG29QxBRlqmmlTrugFs5oqxCi4KRN70KqS
1BjNbHSNzvEoD96Wupr/iEZd72HOs/HrDc8W5EQ8DkfFvSJJB2JHc17fgwKBgGl/
CXa7e9XxgOXvhVD0TRiLSboPWdykvxQ1SvZtnEFjV/6RBfJjPT5fzzpSPg8El46p
C0OBIUIaKYBOWKXBFQeZwjjl5l5rYvuo9viWJ3pBb4Fseg3LoUMEvQ7dZyQKex5V
Nqc5Euh5/yjeBF0yId9u8NUSkVm4D2AA3jfLFa2dAoGAcwNIN0CykHbC9dKhk5ml
iXT8Mwgyz5fHjsw6q6YlIUC0vR4FpuKEA89P7AlNm2C46QCdrDuskTRR2wiNr9jX
ebK9DqmWwLJseJBHG7r31bBwi01mpx6sQKNzt39NFJLnv4ijxwv/ckRqzjyoeFlT
5S7+RPsxPoJK8qN8yCMB0q8=
-----END PRIVATE KEY-----
23 changes: 23 additions & 0 deletions examples/simple.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const Walker = require('..');

const response = "Hello world!";

Walker.get("/", (res) => {
res.sendTextUnchecked(response);
});


Walker.get("/blank", (res) => {
res.uncheckedSendEmptyText();
});

const config = {
url: "0.0.0.0:8081",
workerThreads: 8,
poolPerWorkerSize: 200_000,
backlog: 10000,
debug: false,
tls: false,
}

Walker.startWithConfig(config)
13 changes: 11 additions & 2 deletions examples/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ Walker.get("/template.html", (res) => {
my_var: `We have 10 Page visitors ${++counter}`
};

res.sendTemplateResp('root', 'users/profile.html', JSON.stringify(data));
res.sendTemplateResp('root', 'users/profile.html', JSON.stringify(data));
});

Walker.get("/counter", (res) => {
Expand Down Expand Up @@ -266,4 +266,13 @@ Walker.post("/post", (res) => {
res.sendText(`We got this as the body: ${body.toString('utf8')}`);
});

Walker.startWithWorkerCount("0.0.0.0:8081", 12)
const config = {
url: "0.0.0.0:8081",
workerThreads: 6,
poolPerWorkerSize: 200_000,
backlog: 10000,
debug: false,
tls: false,
}

Walker.startWithConfig(config)
6 changes: 3 additions & 3 deletions examples/testClose.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ const Walker = require('..');

const config = {
url: "0.0.0.0:8081",
worker_threads: "1",
pool_per_worker_size: "100"
worker_threads: 1,
pool_per_worker_size: 100
}

Walker.get("/", (res) => {
res.sendText("Hello world");
res.sendText('Hello world');
});

Walker.startWithConfig(config);
Expand Down
22 changes: 22 additions & 0 deletions examples/tls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const Walker = require('..');

const config = {
url: "0.0.0.0:8081",
workerThreads: 1,
poolPerWorkerSize: 100,
backlog: 10000,
debug: false,
tls: true,
certLocation: './certs/cert.pem',
keyLocation: './certs/key.pem'
}

Walker.get("/", (res) => {
res.sendTextUnchecked("Hello world!");
});

Walker.get("/test", (res) => {
res.sendText("Hello world!");
});

Walker.startWithConfig(config);
55 changes: 55 additions & 0 deletions examples/worker_threads.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const {
Worker,
isMainThread,
setEnvironmentData,
getEnvironmentData,
} = require('node:worker_threads');

const Walker = require('..');
const response = "Hello World!"

if (isMainThread) {

for (let i = 0; i < 6; i++) {
// const worker = new Worker(__filename);
}

Walker.get(`/key`, (res) => {
let i = 0;

for (i; i < 1_000_000; i++) {

}

res.sendTextUnchecked(`Result ${i}`)
})


setTimeout(() => {
console.log('Starting server...')
const config = {
url: "0.0.0.0:8081",
workerThreads: 6,
poolPerWorkerSize: 200_000,
backlog: 10000,
debug: false,
tls: false,
}
Walker.startWithConfig(config);
}, 5000);
} else {
Walker.get(`/`, (res) => {
res.sendTextUnchecked(response);
})

Walker.get(`/key`, (res) => {
let i = 0;

for (; i < 1_000_000; i++) {

}

res.sendTextUnchecked(`Result ${i}`)
})
Walker.registerThreadsPool(200_000);
}
Loading