faastjs
Version:
Serverless batch computing made simple.
106 lines • 17.3 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.testCosts = void 0;
const tslib_1 = require("tslib");
const ava_1 = tslib_1.__importDefault(require("ava"));
const papaparse_1 = tslib_1.__importDefault(require("papaparse"));
const index_1 = require("../index");
const funcs = tslib_1.__importStar(require("./fixtures/functions"));
const util_1 = require("./fixtures/util");
async function work(faastModule) {
await faastModule.functions.monteCarloPI(20000000);
}
const repetitions = 10;
const memorySizes = [1024, 2048];
function filter(configurations) {
return configurations
.filter(c => memorySizes.includes(c.options.memorySize))
.map(c => ({ ...c, repetitions }));
}
async function testCostAnalyzer(t, configurations) {
const profile = await index_1.CostAnalyzer.analyze({
funcs,
work,
configurations,
silent: true
});
t.is(profile.estimates.length, configurations.length);
for (const { costSnapshot } of profile.estimates) {
t.true(costSnapshot.stats.completed > 0, `completed > 0`);
t.is(costSnapshot.stats.errors, 0, `errors === 0`);
t.true(costSnapshot.stats.estimatedBilledTime.mean > 0, `billed time > 0`);
t.true(costSnapshot.total() > 0, `total > 0`);
}
const parsed = papaparse_1.default.parse(profile.csv(), {
header: true,
skipEmptyLines: true,
dynamicTyping: true
});
index_1.log.info(`%O`, parsed.data);
t.is(parsed.data.length, configurations.length);
for (const row of parsed.data) {
// cloud,memory,useQueue,options,completed,errors,retries,cost,executionTime,billedTime
t.is(typeof row.cloud, "string");
t.is(typeof row.memory, "number");
t.is(typeof row.mode, "string");
t.is(typeof row.options, "string");
t.is(typeof row.completed, "number");
t.is(typeof row.errors, "number");
t.is(typeof row.retries, "number");
t.is(typeof row.cost, "string");
t.is(typeof row.executionTime, "number");
t.is(typeof row.billedTime, "number");
}
}
async function testCosts(t, provider) {
const args = {
timeout: 30,
memorySize: 512,
mode: "queue",
maxRetries: 0,
gc: "off",
description: t.title
};
const faastModule = await (0, index_1.faast)(provider, funcs, args);
try {
await faastModule.functions.hello("there");
const costs = await faastModule.costSnapshot();
const { estimatedBilledTime } = faastModule.stats();
t.is((estimatedBilledTime.mean * estimatedBilledTime.samples) / 1000, costs.costMetrics.find(m => m.name === "functionCallDuration").measured);
t.true(costs.costMetrics.length > 1, "cost metrics exist");
t.true(costs.find("functionCallRequests").measured === 1, "functionCallRequests === 1");
const output = costs.toString();
const csvOutput = costs.csv();
let hasPricedMetric = false;
for (const metric of costs.costMetrics) {
t.regex(output, new RegExp(metric.name));
t.regex(csvOutput, new RegExp(metric.name));
if (!metric.informationalOnly) {
t.true(metric.cost() > 0, `${metric.name}.cost() > 0`);
t.true(metric.measured > 0, `${metric.name}.measured > 0`);
t.true(metric.pricing > 0, `${metric.name}.pricing > 0`);
}
hasPricedMetric = true;
t.true(metric.cost() < 0.00001, `${metric.name}.cost() < 0.00001`);
t.true(metric.name.length > 0, `${metric.name}.length > 0`);
t.true(metric.unit.length > 0, `${metric.name}.unit.length > 0`);
t.true(metric.cost() === metric.pricing * metric.measured, `${metric.name} cost is computed correctly`);
}
if (hasPricedMetric) {
t.true(costs.total() >= 0, `costs.total > 0 (hasPricedMetric)`);
}
else {
t.true(costs.total() === 0, `costs.total === 0 (!hasPricedMetric)`);
}
}
finally {
await faastModule.cleanup();
}
}
exports.testCosts = testCosts;
const { awsConfigurations } = index_1.CostAnalyzer;
(0, ava_1.default)((0, util_1.title)("aws", "cost analyzer"), testCostAnalyzer, filter(awsConfigurations));
for (const provider of index_1.providers) {
(0, ava_1.default)((0, util_1.title)(provider, `cost estimate for basic calls`), testCosts, provider);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29zdC50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdGVzdC9jb3N0LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLHNEQUE2QztBQUM3QyxrRUFBNEI7QUFDNUIsb0NBUWtCO0FBQ2xCLG9FQUE4QztBQUM5QywwQ0FBd0M7QUFFeEMsS0FBSyxVQUFVLElBQUksQ0FBQyxXQUFzQztJQUN0RCxNQUFNLFdBQVcsQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ3ZELENBQUM7QUFFRCxNQUFNLFdBQVcsR0FBRyxFQUFFLENBQUM7QUFDdkIsTUFBTSxXQUFXLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFFakMsU0FBUyxNQUFNLENBQUMsY0FBNEM7SUFDeEQsT0FBTyxjQUFjO1NBQ2hCLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFXLENBQUMsQ0FBQztTQUN4RCxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzNDLENBQUM7QUFFRCxLQUFLLFVBQVUsZ0JBQWdCLENBQzNCLENBQW1CLEVBQ25CLGNBQTRDO0lBRTVDLE1BQU0sT0FBTyxHQUFHLE1BQU0sb0JBQVksQ0FBQyxPQUFPLENBQUM7UUFDdkMsS0FBSztRQUNMLElBQUk7UUFDSixjQUFjO1FBQ2QsTUFBTSxFQUFFLElBQUk7S0FDZixDQUFDLENBQUM7SUFDSCxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0RCxLQUFLLE1BQU0sRUFBRSxZQUFZLEVBQUUsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDL0MsQ0FB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QUUsQ0FBQztJQUNoQyxDQUFDO0FBQ0wsQ0FBQztBQXRERCw4QkFzREM7QUFFRCxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsR0FBRyxvQkFBWSxDQUFDO0FBQzNDLElBQUEsYUFBSSxFQUFDLElBQUEsWUFBSyxFQUFDLEtBQUssRUFBRSxlQUFlLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO0FBRWpGLEtBQUssTUFBTSxRQUFRLElBQUksaUJBQVMsRUFBRSxDQUFDO0lBQy9CLElBQUEsYUFBSSxFQUFDLElBQUEsWUFBSyxFQUFDLFFBQVEsRUFBRSwrQkFBK0IsQ0FBQyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztBQUNoRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHRlc3QsIHsgRXhlY3V0aW9uQ29udGV4dCB9IGZyb20gXCJhdmFcIjtcbmltcG9ydCBwcHAgZnJvbSBcInBhcGFwYXJzZVwiO1xuaW1wb3J0IHtcbiAgICBDb21tb25PcHRpb25zLFxuICAgIGZhYXN0LFxuICAgIEZhYXN0TW9kdWxlLFxuICAgIGxvZyxcbiAgICBQcm92aWRlcixcbiAgICBwcm92aWRlcnMsXG4gICAgQ29zdEFuYWx5emVyXG59IGZyb20gXCIuLi9pbmRleFwiO1xuaW1wb3J0ICogYXMgZnVuY3MgZnJvbSBcIi4vZml4dHVyZXMvZnVuY3Rpb25zXCI7XG5pbXBvcnQgeyB0aXRsZSB9IGZyb20gXCIuL2ZpeHR1cmVzL3V0aWxcIjtcblxuYXN5bmMgZnVuY3Rpb24gd29yayhmYWFzdE1vZHVsZTogRmFhc3RNb2R1bGU8dHlwZW9mIGZ1bmNzPikge1xuICAgIGF3YWl0IGZhYXN0TW9kdWxlLmZ1bmN0aW9ucy5tb250ZUNhcmxvUEkoMjAwMDAwMDApO1xufVxuXG5jb25zdCByZXBldGl0aW9ucyA9IDEwO1xuY29uc3QgbWVtb3J5U2l6ZXMgPSBbMTAyNCwgMjA0OF07XG5cbmZ1bmN0aW9uIGZpbHRlcihjb25maWd1cmF0aW9uczogQ29zdEFuYWx5emVyLkNvbmZpZ3VyYXRpb25bXSkge1xuICAgIHJldHVybiBjb25maWd1cmF0aW9uc1xuICAgICAgICAuZmlsdGVyKGMgPT4gbWVtb3J5U2l6ZXMuaW5jbHVkZXMoYy5vcHRpb25zLm1lbW9yeVNpemUhKSlcbiAgICAgICAgLm1hcChjID0+ICh7IC4uLmMsIHJlcGV0aXRpb25zIH0pKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdGVzdENvc3RBbmFseXplcihcbiAgICB0OiBFeGVjdXRpb25Db250ZXh0LFxuICAgIGNvbmZpZ3VyYXRpb25zOiBDb3N0QW5hbHl6ZXIuQ29uZmlndXJhdGlvbltdXG4pIHtcbiAgICBjb25zdCBwcm9maWxlID0gYXdhaXQgQ29zdEFuYWx5emVyLmFuYWx5emUoe1xuICAgICAgICBmdW5jcyxcbiAgICAgICAgd29yayxcbiAgICAgICAgY29uZmlndXJhdGlvbnMsXG4gICAgICAgIHNpbGVudDogdHJ1ZVxuICAgIH0pO1xuICAgIHQuaXMocHJvZmlsZS5lc3RpbWF0ZXMubGVuZ3RoLCBjb25maWd1cmF0aW9ucy5sZW5ndGgpO1xuICAgIGZvciAoY29uc3QgeyBjb3N0U25hcHNob3QgfSBvZiBwcm9maWxlLmVzdGltYXRlcykge1xuICAgICAgICB0LnRydWUoY29zdFNuYXBzaG90LnN0YXRzLmNvbXBsZXRlZCA+IDAsIGBjb21wbGV0ZWQgPiAwYCk7XG4gICAgICAgIHQuaXMoY29zdFNuYXBzaG90LnN0YXRzLmVycm9ycywgMCwgYGVycm9ycyA9PT0gMGApO1xuICAgICAgICB0LnRydWUoY29zdFNuYXBzaG90LnN0YXRzLmVzdGltYXRlZEJpbGxlZFRpbWUubWVhbiA+IDAsIGBiaWxsZWQgdGltZSA+IDBgKTtcbiAgICAgICAgdC50cnVlKGNvc3RTbmFwc2hvdC50b3RhbCgpID4gMCwgYHRvdGFsID4gMGApO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlZCA9IHBwcC5wYXJzZTxhbnk+KHByb2ZpbGUuY3N2KCksIHtcbiAgICAgICAgaGVhZGVyOiB0cnVlLFxuICAgICAgICBza2lwRW1wdHlMaW5lczogdHJ1ZSxcbiAgICAgICAgZHluYW1pY1R5cGluZzogdHJ1ZVxuICAgIH0pO1xuICAgIGxvZy5pbmZvKGAlT2AsIHBhcnNlZC5kYXRhKTtcbiAgICB0LmlzKHBhcnNlZC5kYXRhLmxlbmd0aCwgY29uZmlndXJhdGlvbnMubGVuZ3RoKTtcblxuICAgIGZvciAoY29uc3Qgcm93IG9mIHBhcnNlZC5kYXRhKSB7XG4gICAgICAgIC8vIGNsb3VkLG1lbW9yeSx1c2VRdWV1ZSxvcHRpb25zLGNvbXBsZXRlZCxlcnJvcnMscmV0cmllcyxjb3N0LGV4ZWN1dGlvblRpbWUsYmlsbGVkVGltZVxuICAgICAgICB0LmlzKHR5cGVvZiByb3cuY2xvdWQsIFwic3RyaW5nXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cubWVtb3J5LCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93Lm1vZGUsIFwic3RyaW5nXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cub3B0aW9ucywgXCJzdHJpbmdcIik7XG4gICAgICAgIHQuaXModHlwZW9mIHJvdy5jb21wbGV0ZWQsIFwibnVtYmVyXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cuZXJyb3JzLCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93LnJldHJpZXMsIFwibnVtYmVyXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cuY29zdCwgXCJzdHJpbmdcIik7XG4gICAgICAgIHQuaXModHlwZW9mIHJvdy5leGVjdXRpb25UaW1lLCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93LmJpbGxlZFRpbWUsIFwibnVtYmVyXCIpO1xuICAgIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRlc3RDb3N0cyh0OiBFeGVjdXRpb25Db250ZXh0LCBwcm92aWRlcjogUHJvdmlkZXIpIHtcbiAgICBjb25zdCBhcmdzOiBDb21tb25PcHRpb25zID0ge1xuICAgICAgICB0aW1lb3V0OiAzMCxcbiAgICAgICAgbWVtb3J5U2l6ZTogNTEyLFxuICAgICAgICBtb2RlOiBcInF1ZXVlXCIsXG4gICAgICAgIG1heFJldHJpZXM6IDAsXG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZVxuICAgIH07XG4gICAgY29uc3QgZmFhc3RNb2R1bGUgPSBhd2FpdCBmYWFzdChwcm92aWRlciwgZnVuY3MsIGFyZ3MpO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuZnVuY3Rpb25zLmhlbGxvKFwidGhlcmVcIik7XG4gICAgICAgIGNvbnN0IGNvc3RzID0gYXdhaXQgZmFhc3RNb2R1bGUuY29zdFNuYXBzaG90KCk7XG5cbiAgICAgICAgY29uc3QgeyBlc3RpbWF0ZWRCaWxsZWRUaW1lIH0gPSBmYWFzdE1vZHVsZS5zdGF0cygpO1xuICAgICAgICB0LmlzKFxuICAgICAgICAgICAgKGVzdGltYXRlZEJpbGxlZFRpbWUubWVhbiAqIGVzdGltYXRlZEJpbGxlZFRpbWUuc2FtcGxlcykgLyAxMDAwLFxuICAgICAgICAgICAgY29zdHMuY29zdE1ldHJpY3MuZmluZChtID0+IG0ubmFtZSA9PT0gXCJmdW5jdGlvbkNhbGxEdXJhdGlvblwiKSEubWVhc3VyZWRcbiAgICAgICAgKTtcblxuICAgICAgICB0LnRydWUoY29zdHMuY29zdE1ldHJpY3MubGVuZ3RoID4gMSwgXCJjb3N0IG1ldHJpY3MgZXhpc3RcIik7XG4gICAgICAgIHQudHJ1ZShcbiAgICAgICAgICAgIGNvc3RzLmZpbmQoXCJmdW5jdGlvbkNhbGxSZXF1ZXN0c1wiKSEubWVhc3VyZWQgPT09IDEsXG4gICAgICAgICAgICBcImZ1bmN0aW9uQ2FsbFJlcXVlc3RzID09PSAxXCJcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3Qgb3V0cHV0ID0gY29zdHMudG9TdHJpbmcoKTtcbiAgICAgICAgY29uc3QgY3N2T3V0cHV0ID0gY29zdHMuY3N2KCk7XG4gICAgICAgIGxldCBoYXNQcmljZWRNZXRyaWMgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCBtZXRyaWMgb2YgY29zdHMuY29zdE1ldHJpY3MpIHtcbiAgICAgICAgICAgIHQucmVnZXgob3V0cHV0LCBuZXcgUmVnRXhwKG1ldHJpYy5uYW1lKSk7XG4gICAgICAgICAgICB0LnJlZ2V4KGNzdk91dHB1dCwgbmV3IFJlZ0V4cChtZXRyaWMubmFtZSkpO1xuICAgICAgICAgICAgaWYgKCFtZXRyaWMuaW5mb3JtYXRpb25hbE9ubHkpIHtcbiAgICAgICAgICAgICAgICB0LnRydWUobWV0cmljLmNvc3QoKSA+IDAsIGAke21ldHJpYy5uYW1lfS5jb3N0KCkgPiAwYCk7XG4gICAgICAgICAgICAgICAgdC50cnVlKG1ldHJpYy5tZWFzdXJlZCA+IDAsIGAke21ldHJpYy5uYW1lfS5tZWFzdXJlZCA+IDBgKTtcbiAgICAgICAgICAgICAgICB0LnRydWUobWV0cmljLnByaWNpbmcgPiAwLCBgJHttZXRyaWMubmFtZX0ucHJpY2luZyA+IDBgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhc1ByaWNlZE1ldHJpYyA9IHRydWU7XG4gICAgICAgICAgICB0LnRydWUobWV0cmljLmNvc3QoKSA8IDAuMDAwMDEsIGAke21ldHJpYy5uYW1lfS5jb3N0KCkgPCAwLjAwMDAxYCk7XG4gICAgICAgICAgICB0LnRydWUobWV0cmljLm5hbWUubGVuZ3RoID4gMCwgYCR7bWV0cmljLm5hbWV9Lmxlbmd0aCA+IDBgKTtcbiAgICAgICAgICAgIHQudHJ1ZShtZXRyaWMudW5pdC5sZW5ndGggPiAwLCBgJHttZXRyaWMubmFtZX0udW5pdC5sZW5ndGggPiAwYCk7XG4gICAgICAgICAgICB0LnRydWUoXG4gICAgICAgICAgICAgICAgbWV0cmljLmNvc3QoKSA9PT0gbWV0cmljLnByaWNpbmcgKiBtZXRyaWMubWVhc3VyZWQsXG4gICAgICAgICAgICAgICAgYCR7bWV0cmljLm5hbWV9IGNvc3QgaXMgY29tcHV0ZWQgY29ycmVjdGx5YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGFzUHJpY2VkTWV0cmljKSB7XG4gICAgICAgICAgICB0LnRydWUoY29zdHMudG90YWwoKSA+PSAwLCBgY29zdHMudG90YWwgPiAwIChoYXNQcmljZWRNZXRyaWMpYCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0LnRydWUoY29zdHMudG90YWwoKSA9PT0gMCwgYGNvc3RzLnRvdGFsID09PSAwICghaGFzUHJpY2VkTWV0cmljKWApO1xuICAgICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuY2xlYW51cCgpO1xuICAgIH1cbn1cblxuY29uc3QgeyBhd3NDb25maWd1cmF0aW9ucyB9ID0gQ29zdEFuYWx5emVyO1xudGVzdCh0aXRsZShcImF3c1wiLCBcImNvc3QgYW5hbHl6ZXJcIiksIHRlc3RDb3N0QW5hbHl6ZXIsIGZpbHRlcihhd3NDb25maWd1cmF0aW9ucykpO1xuXG5mb3IgKGNvbnN0IHByb3ZpZGVyIG9mIHByb3ZpZGVycykge1xuICAgIHRlc3QodGl0bGUocHJvdmlkZXIsIGBjb3N0IGVzdGltYXRlIGZvciBiYXNpYyBjYWxsc2ApLCB0ZXN0Q29zdHMsIHByb3ZpZGVyKTtcbn1cbiJdfQ==
;