UNPKG

12.9 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const ava_1 = require("ava");
4const index_1 = require("../index");
5const funcs = require("../test/fixtures/functions");
6const util_1 = require("../test/fixtures/util");
7const throttle_1 = require("../src/throttle");
8async function throughput(t, provider, options) {
9 const lambda = await (0, index_1.faast)(provider, funcs, {
10 gc: "off",
11 description: t.title,
12 ...options
13 });
14 lambda.on("stats", s => console.log(s.toString()));
15 try {
16 let completed = 0;
17 const nSamplesPerFunction = 100000000;
18 const pump = new throttle_1.Pump({ concurrency: options.concurrency }, () => lambda.functions.monteCarloPI(nSamplesPerFunction).then(() => completed++));
19 pump.start();
20 await (0, util_1.sleep)(options.duration);
21 await pump.drain();
22 const cost = await lambda.costSnapshot();
23 console.log(`Stats: ${lambda.stats()}`);
24 console.log(`Cost:`);
25 console.log(`${cost}`);
26 console.log(`Completed ${completed} calls in ${options.duration / (60 * 1000)} minute(s)`);
27 }
28 finally {
29 await lambda.cleanup();
30 }
31}
32async function rampUp(t, provider, options) {
33 const lambda = await (0, index_1.faast)(provider, funcs, {
34 gc: "off",
35 description: t.title,
36 ...options
37 });
38 lambda.on("stats", s => console.log(s.toString()));
39 try {
40 const nParallelFunctions = 500;
41 const nSamplesPerFunction = 2000000;
42 const promises = [];
43 for (let i = 0; i < nParallelFunctions; i++) {
44 promises.push(lambda.functions.monteCarloPI(nSamplesPerFunction));
45 }
46 const results = await Promise.all(promises);
47 let insidePoints = 0;
48 let samplePoints = 0;
49 results.forEach(m => {
50 insidePoints += m.inside;
51 samplePoints += m.samples;
52 });
53 console.log(`Stats:\n${lambda.stats()}`);
54 console.log(`inside: ${insidePoints}, samples: ${samplePoints}`);
55 t.is(samplePoints, nParallelFunctions * nSamplesPerFunction);
56 const estimatedPI = (insidePoints / samplePoints) * 4;
57 console.log(`PI estimate: ${estimatedPI}`);
58 t.is(Number(estimatedPI.toFixed(2)), 3.14);
59 const cost = await lambda.costSnapshot();
60 console.log(`Cost: ${cost}`);
61 }
62 finally {
63 await lambda.cleanup();
64 }
65}
66const rampUpConfigurations = [
67 { memorySize: 1024, mode: "https", concurrency: 500 },
68 { memorySize: 1024, mode: "queue", concurrency: 500 }
69];
70for (const provider of index_1.providers) {
71 for (const config of rampUpConfigurations) {
72 ava_1.default.serial((0, util_1.title)(provider, "ramp up", config), rampUp, provider, config);
73 }
74}
75const throughputConfigurations = [
76 { memorySize: 2048, mode: "https", concurrency: 500, duration: 180 * 1000 },
77 { memorySize: 2048, mode: "queue", concurrency: 500, duration: 180 * 1000 }
78];
79for (const provider of index_1.providers) {
80 for (const config of throughputConfigurations) {
81 ava_1.default.serial((0, util_1.title)(provider, "throughput load test", config), throughput, provider, config);
82 }
83}
84ava_1.default.serial(throughput, "local", { memorySize: 64, duration: 60 * 1000 });
85//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVyZm9ybWFuY2UudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3Rlc3QtcGVyZi9wZXJmb3JtYW5jZS50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNkJBQTZDO0FBQzdDLG9DQUFxRTtBQUNyRSxvREFBb0Q7QUFDcEQsZ0RBQXFEO0FBQ3JELDhDQUF1QztBQUV2QyxLQUFLLFVBQVUsVUFBVSxDQUNyQixDQUFtQixFQUNuQixRQUFrQixFQUNsQixPQUE2QztJQUU3QyxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEsYUFBSyxFQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUU7UUFDeEMsRUFBRSxFQUFFLEtBQUs7UUFDVCxXQUFXLEVBQUUsQ0FBQyxDQUFDLEtBQUs7UUFDcEIsR0FBRyxPQUFPO0tBQ2IsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFbkQsSUFBSTtRQUNBLElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQztRQUNsQixNQUFNLG1CQUFtQixHQUFHLFNBQVMsQ0FBQztRQUN0QyxNQUFNLElBQUksR0FBRyxJQUFJLGVBQUksQ0FBQyxFQUFFLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBWSxFQUFFLEVBQUUsR0FBRyxFQUFFLENBQzlELE1BQU0sQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLG1CQUFtQixDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQzdFLENBQUM7UUFDRixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDYixNQUFNLElBQUEsWUFBSyxFQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM5QixNQUFNLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNuQixNQUFNLElB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dGlvbkNvbnRleHQgfSBmcm9tIFwiYXZhXCI7XG5pbXBvcnQgeyBDb21tb25PcHRpb25zLCBmYWFzdCwgUHJvdmlkZXIsIHByb3ZpZGVycyB9IGZyb20gXCIuLi9pbmRleFwiO1xuaW1wb3J0ICogYXMgZnVuY3MgZnJvbSBcIi4uL3Rlc3QvZml4dHVyZXMvZnVuY3Rpb25zXCI7XG5pbXBvcnQgeyBzbGVlcCwgdGl0bGUgfSBmcm9tIFwiLi4vdGVzdC9maXh0dXJlcy91dGlsXCI7XG5pbXBvcnQgeyBQdW1wIH0gZnJvbSBcIi4uL3NyYy90aHJvdHRsZVwiO1xuXG5hc3luYyBmdW5jdGlvbiB0aHJvdWdocHV0KFxuICAgIHQ6IEV4ZWN1dGlvbkNvbnRleHQsXG4gICAgcHJvdmlkZXI6IFByb3ZpZGVyLFxuICAgIG9wdGlvbnM6IENvbW1vbk9wdGlvbnMgJiB7IGR1cmF0aW9uOiBudW1iZXIgfVxuKSB7XG4gICAgY29uc3QgbGFtYmRhID0gYXdhaXQgZmFhc3QocHJvdmlkZXIsIGZ1bmNzLCB7XG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZSxcbiAgICAgICAgLi4ub3B0aW9uc1xuICAgIH0pO1xuICAgIGxhbWJkYS5vbihcInN0YXRzXCIsIHMgPT4gY29uc29sZS5sb2cocy50b1N0cmluZygpKSk7XG5cbiAgICB0cnkge1xuICAgICAgICBsZXQgY29tcGxldGVkID0gMDtcbiAgICAgICAgY29uc3QgblNhbXBsZXNQZXJGdW5jdGlvbiA9IDEwMDAwMDAwMDtcbiAgICAgICAgY29uc3QgcHVtcCA9IG5ldyBQdW1wKHsgY29uY3VycmVuY3k6IG9wdGlvbnMuY29uY3VycmVuY3khIH0sICgpID0+XG4gICAgICAgICAgICBsYW1iZGEuZnVuY3Rpb25zLm1vbnRlQ2FybG9QSShuU2FtcGxlc1BlckZ1bmN0aW9uKS50aGVuKCgpID0+IGNvbXBsZXRlZCsrKVxuICAgICAgICApO1xuICAgICAgICBwdW1wLnN0YXJ0KCk7XG4gICAgICAgIGF3YWl0IHNsZWVwKG9wdGlvbnMuZHVyYXRpb24pO1xuICAgICAgICBhd2FpdCBwdW1wLmRyYWluKCk7XG4gICAgICAgIGNvbnN0IGNvc3QgPSBhd2FpdCBsYW1iZGEuY29zdFNuYXBzaG90KCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBTdGF0czogJHtsYW1iZGEuc3RhdHMoKX1gKTtcbiAgICAgICAgY29uc29sZS5sb2coYENvc3Q6YCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGAke2Nvc3R9YCk7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgYENvbXBsZXRlZCAke2NvbXBsZXRlZH0gY2FsbHMgaW4gJHtvcHRpb25zLmR1cmF0aW9uIC8gKDYwICogMTAwMCl9IG1pbnV0ZShzKWBcbiAgICAgICAgKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBsYW1iZGEuY2xlYW51cCgpO1xuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcmFtcFVwKHQ6IEV4ZWN1dGlvbkNvbnRleHQsIHByb3ZpZGVyOiBQcm92aWRlciwgb3B0aW9uczogQ29tbW9uT3B0aW9ucykge1xuICAgIGNvbnN0IGxhbWJkYSA9IGF3YWl0IGZhYXN0KHByb3ZpZGVyLCBmdW5jcywge1xuICAgICAgICBnYzogXCJvZmZcIixcbiAgICAgICAgZGVzY3JpcHRpb246IHQudGl0bGUsXG4gICAgICAgIC4uLm9wdGlvbnNcbiAgICB9KTtcbiAgICBsYW1iZGEub24oXCJzdGF0c1wiLCBzID0+IGNvbnNvbGUubG9nKHMudG9TdHJpbmcoKSkpO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgblBhcmFsbGVsRnVuY3Rpb25zID0gNTAwO1xuICAgICAgICBjb25zdCBuU2FtcGxlc1BlckZ1bmN0aW9uID0gMjAwMDAwMDtcbiAgICAgICAgY29uc3QgcHJvbWlzZXM6IFByb21pc2U8ZnVuY3MuTW9udGVDYXJsb1JldHVybj5bXSA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5QYXJhbGxlbEZ1bmN0aW9uczsgaSsrKSB7XG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKGxhbWJkYS5mdW5jdGlvbnMubW9udGVDYXJsb1BJKG5TYW1wbGVzUGVyRnVuY3Rpb24pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgICAgIGxldCBpbnNpZGVQb2ludHMgPSAwO1xuICAgICAgICBsZXQgc2FtcGxlUG9pbnRzID0gMDtcblxuICAgICAgICByZXN1bHRzLmZvckVhY2gobSA9PiB7XG4gICAgICAgICAgICBpbnNpZGVQb2ludHMgKz0gbS5pbnNpZGU7XG4gICAgICAgICAgICBzYW1wbGVQb2ludHMgKz0gbS5zYW1wbGVzO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmxvZyhgU3RhdHM6XFxuJHtsYW1iZGEuc3RhdHMoKX1gKTtcbiAgICAgICAgY29uc29sZS5sb2coYGluc2lkZTogJHtpbnNpZGVQb2ludHN9LCBzYW1wbGVzOiAke3NhbXBsZVBvaW50c31gKTtcbiAgICAgICAgdC5pcyhzYW1wbGVQb2ludHMsIG5QYXJhbGxlbEZ1bmN0aW9ucyAqIG5TYW1wbGVzUGVyRnVuY3Rpb24pO1xuICAgICAgICBjb25zdCBlc3RpbWF0ZWRQSSA9IChpbnNpZGVQb2ludHMgLyBzYW1wbGVQb2ludHMpICogNDtcbiAgICAgICAgY29uc29sZS5sb2coYFBJIGVzdGltYXRlOiAke2VzdGltYXRlZFBJfWApO1xuICAgICAgICB0LmlzKE51bWJlcihlc3RpbWF0ZWRQSS50b0ZpeGVkKDIpKSwgMy4xNCk7XG4gICAgICAgIGNvbnN0IGNvc3QgPSBhd2FpdCBsYW1iZGEuY29zdFNuYXBzaG90KCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBDb3N0OiAke2Nvc3R9YCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgbGFtYmRhLmNsZWFudXAoKTtcbiAgICB9XG59XG5cbmNvbnN0IHJhbXBVcENvbmZpZ3VyYXRpb25zID0gW1xuICAgIHsgbWVtb3J5U2l6ZTogMTAyNCwgbW9kZTogXCJodHRwc1wiLCBjb25jdXJyZW5jeTogNTAwIH0sXG4gICAgeyBtZW1vcnlTaXplOiAxMDI0LCBtb2RlOiBcInF1ZXVlXCIsIGNvbmN1cnJlbmN5OiA1MDAgfVxuXSBhcyBjb25zdDtcblxuZm9yIChjb25zdCBwcm92aWRlciBvZiBwcm92aWRlcnMpIHtcbiAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiByYW1wVXBDb25maWd1cmF0aW9ucykge1xuICAgICAgICB0ZXN0LnNlcmlhbCh0aXRsZShwcm92aWRlciwgXCJyYW1wIHVwXCIsIGNvbmZpZyksIHJhbXBVcCwgcHJvdmlkZXIsIGNvbmZpZyk7XG4gICAgfVxufVxuXG5jb25zdCB0aHJvdWdocHV0Q29uZmlndXJhdGlvbnMgPSBbXG4gICAgeyBtZW1vcnlTaXplOiAyMDQ4LCBtb2RlOiBcImh0dHBzXCIsIGNvbmN1cnJlbmN5OiA1MDAsIGR1cmF0aW9uOiAxODAgKiAxMDAwIH0sXG4gICAgeyBtZW1vcnlTaXplOiAyMDQ4LCBtb2RlOiBcInF1ZXVlXCIsIGNvbmN1cnJlbmN5OiA1MDAsIGR1cmF0aW9uOiAxODAgKiAxMDAwIH1cbl0gYXMgY29uc3Q7XG5cbmZvciAoY29uc3QgcHJvdmlkZXIgb2YgcHJvdmlkZXJzKSB7XG4gICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhyb3VnaHB1dENvbmZpZ3VyYXRpb25zKSB7XG4gICAgICAgIHRlc3Quc2VyaWFsKFxuICAgICAgICAgICAgdGl0bGUocHJvdmlkZXIsIFwidGhyb3VnaHB1dCBsb2FkIHRlc3RcIiwgY29uZmlnKSxcbiAgICAgICAgICAgIHRocm91Z2hwdXQsXG4gICAgICAgICAgICBwcm92aWRlcixcbiAgICAgICAgICAgIGNvbmZpZ1xuICAgICAgICApO1xuICAgIH1cbn1cblxudGVzdC5zZXJpYWwodGhyb3VnaHB1dCwgXCJsb2NhbFwiLCB7IG1lbW9yeVNpemU6IDY0LCBkdXJhdGlvbjogNjAgKiAxMDAwIH0pO1xuIl19
\No newline at end of file