UNPKG

faastjs

Version:

Serverless batch computing made simple.

106 lines 17.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.testCosts = void 0; const ava_1 = require("ava"); const ppp = require("papaparse"); const index_1 = require("../index"); const funcs = 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 = ppp.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, googleConfigurations } = index_1.CostAnalyzer; (0, ava_1.default)((0, util_1.title)("aws", "cost analyzer"), testCostAnalyzer, filter(awsConfigurations)); (0, ava_1.default)((0, util_1.title)("google", "cost analyzer"), testCostAnalyzer, filter(googleConfigurations)); 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29zdC50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdGVzdC9jb3N0LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQTZDO0FBQzdDLGlDQUFpQztBQUNqQyxvQ0FRa0I7QUFDbEIsOENBQThDO0FBQzlDLDBDQUF3QztBQUV4QyxLQUFLLFVBQVUsSUFBSSxDQUFDLFdBQXNDO0lBQ3RELE1BQU0sV0FBVyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDdkQsQ0FBQztBQUVELE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQztBQUN2QixNQUFNLFdBQVcsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztBQUVqQyxTQUFTLE1BQU0sQ0FBQyxjQUE0QztJQUN4RCxPQUFPLGNBQWM7U0FDaEIsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFVBQVcsQ0FBQyxDQUFDO1NBQ3hELEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxnQkFBZ0IsQ0FDM0IsQ0FBbUIsRUFDbkIsY0FBNEM7SUFFNUMsTUFBTSxPQUFPLEdBQUcsTUFBTSxvQkFBWSxDQUFDLE9BQU8sQ0FBQztRQUN2QyxLQUFLO1FBQ0wsSUFBSTtRQUNKLGNBQWM7UUFDZCxNQUFNLEVBQUUsSUFBSTtLQUNmLENBQUMsQ0FBQztJQUNILENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3RELEtBQUssTUFBTSxFQUFFLFlBQVksRUFBRSxJQUFJLE9BQU8sQ0FBQyxTQUFTLEVBQUU7UUFDOUMsQ0FBQyxDQUFD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QUFHLG9CQUFZLENBQUM7QUFDakUsSUFBQSxhQUFJLEVBQUMsSUFBQSxZQUFLLEVBQUMsS0FBSyxFQUFFLGVBQWUsQ0FBQyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7QUFDakYsSUFBQSxhQUFJLEVBQUMsSUFBQSxZQUFLLEVBQUMsUUFBUSxFQUFFLGVBQWUsQ0FBQyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUM7QUFFdkYsS0FBSyxNQUFNLFFBQVEsSUFBSSxpQkFBUyxFQUFFO0lBQzlCLElBQUEsYUFBSSxFQUFDLElBQUEsWUFBSyxFQUFDLFFBQVEsRUFBRSwrQkFBK0IsQ0FBQyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztDQUMvRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0ZXN0LCB7IEV4ZWN1dGlvbkNvbnRleHQgfSBmcm9tIFwiYXZhXCI7XG5pbXBvcnQgKiBhcyBwcHAgZnJvbSBcInBhcGFwYXJzZVwiO1xuaW1wb3J0IHtcbiAgICBDb21tb25PcHRpb25zLFxuICAgIGZhYXN0LFxuICAgIEZhYXN0TW9kdWxlLFxuICAgIGxvZyxcbiAgICBQcm92aWRlcixcbiAgICBwcm92aWRlcnMsXG4gICAgQ29zdEFuYWx5emVyXG59IGZyb20gXCIuLi9pbmRleFwiO1xuaW1wb3J0ICogYXMgZnVuY3MgZnJvbSBcIi4vZml4dHVyZXMvZnVuY3Rpb25zXCI7XG5pbXBvcnQgeyB0aXRsZSB9IGZyb20gXCIuL2ZpeHR1cmVzL3V0aWxcIjtcblxuYXN5bmMgZnVuY3Rpb24gd29yayhmYWFzdE1vZHVsZTogRmFhc3RNb2R1bGU8dHlwZW9mIGZ1bmNzPikge1xuICAgIGF3YWl0IGZhYXN0TW9kdWxlLmZ1bmN0aW9ucy5tb250ZUNhcmxvUEkoMjAwMDAwMDApO1xufVxuXG5jb25zdCByZXBldGl0aW9ucyA9IDEwO1xuY29uc3QgbWVtb3J5U2l6ZXMgPSBbMTAyNCwgMjA0OF07XG5cbmZ1bmN0aW9uIGZpbHRlcihjb25maWd1cmF0aW9uczogQ29zdEFuYWx5emVyLkNvbmZpZ3VyYXRpb25bXSkge1xuICAgIHJldHVybiBjb25maWd1cmF0aW9uc1xuICAgICAgICAuZmlsdGVyKGMgPT4gbWVtb3J5U2l6ZXMuaW5jbHVkZXMoYy5vcHRpb25zLm1lbW9yeVNpemUhKSlcbiAgICAgICAgLm1hcChjID0+ICh7IC4uLmMsIHJlcGV0aXRpb25zIH0pKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdGVzdENvc3RBbmFseXplcihcbiAgICB0OiBFeGVjdXRpb25Db250ZXh0LFxuICAgIGNvbmZpZ3VyYXRpb25zOiBDb3N0QW5hbHl6ZXIuQ29uZmlndXJhdGlvbltdXG4pIHtcbiAgICBjb25zdCBwcm9maWxlID0gYXdhaXQgQ29zdEFuYWx5emVyLmFuYWx5emUoe1xuICAgICAgICBmdW5jcyxcbiAgICAgICAgd29yayxcbiAgICAgICAgY29uZmlndXJhdGlvbnMsXG4gICAgICAgIHNpbGVudDogdHJ1ZVxuICAgIH0pO1xuICAgIHQuaXMocHJvZmlsZS5lc3RpbWF0ZXMubGVuZ3RoLCBjb25maWd1cmF0aW9ucy5sZW5ndGgpO1xuICAgIGZvciAoY29uc3QgeyBjb3N0U25hcHNob3QgfSBvZiBwcm9maWxlLmVzdGltYXRlcykge1xuICAgICAgICB0LnRydWUoY29zdFNuYXBzaG90LnN0YXRzLmNvbXBsZXRlZCA+IDAsIGBjb21wbGV0ZWQgPiAwYCk7XG4gICAgICAgIHQuaXMoY29zdFNuYXBzaG90LnN0YXRzLmVycm9ycywgMCwgYGVycm9ycyA9PT0gMGApO1xuICAgICAgICB0LnRydWUoY29zdFNuYXBzaG90LnN0YXRzLmVzdGltYXRlZEJpbGxlZFRpbWUubWVhbiA+IDAsIGBiaWxsZWQgdGltZSA+IDBgKTtcbiAgICAgICAgdC50cnVlKGNvc3RTbmFwc2hvdC50b3RhbCgpID4gMCwgYHRvdGFsID4gMGApO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlZCA9IHBwcC5wYXJzZTxhbnk+KHByb2ZpbGUuY3N2KCksIHtcbiAgICAgICAgaGVhZGVyOiB0cnVlLFxuICAgICAgICBza2lwRW1wdHlMaW5lczogdHJ1ZSxcbiAgICAgICAgZHluYW1pY1R5cGluZzogdHJ1ZVxuICAgIH0pO1xuICAgIGxvZy5pbmZvKGAlT2AsIHBhcnNlZC5kYXRhKTtcbiAgICB0LmlzKHBhcnNlZC5kYXRhLmxlbmd0aCwgY29uZmlndXJhdGlvbnMubGVuZ3RoKTtcblxuICAgIGZvciAoY29uc3Qgcm93IG9mIHBhcnNlZC5kYXRhKSB7XG4gICAgICAgIC8vIGNsb3VkLG1lbW9yeSx1c2VRdWV1ZSxvcHRpb25zLGNvbXBsZXRlZCxlcnJvcnMscmV0cmllcyxjb3N0LGV4ZWN1dGlvblRpbWUsYmlsbGVkVGltZVxuICAgICAgICB0LmlzKHR5cGVvZiByb3cuY2xvdWQsIFwic3RyaW5nXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cubWVtb3J5LCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93Lm1vZGUsIFwic3RyaW5nXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cub3B0aW9ucywgXCJzdHJpbmdcIik7XG4gICAgICAgIHQuaXModHlwZW9mIHJvdy5jb21wbGV0ZWQsIFwibnVtYmVyXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cuZXJyb3JzLCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93LnJldHJpZXMsIFwibnVtYmVyXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cuY29zdCwgXCJzdHJpbmdcIik7XG4gICAgICAgIHQuaXModHlwZW9mIHJvdy5leGVjdXRpb25UaW1lLCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93LmJpbGxlZFRpbWUsIFwibnVtYmVyXCIpO1xuICAgIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRlc3RDb3N0cyh0OiBFeGVjdXRpb25Db250ZXh0LCBwcm92aWRlcjogUHJvdmlkZXIpIHtcbiAgICBjb25zdCBhcmdzOiBDb21tb25PcHRpb25zID0ge1xuICAgICAgICB0aW1lb3V0OiAzMCxcbiAgICAgICAgbWVtb3J5U2l6ZTogNTEyLFxuICAgICAgICBtb2RlOiBcInF1ZXVlXCIsXG4gICAgICAgIG1heFJldHJpZXM6IDAsXG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZVxuICAgIH07XG4gICAgY29uc3QgZmFhc3RNb2R1bGUgPSBhd2FpdCBmYWFzdChwcm92aWRlciwgZnVuY3MsIGFyZ3MpO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuZnVuY3Rpb25zLmhlbGxvKFwidGhlcmVcIik7XG4gICAgICAgIGNvbnN0IGNvc3RzID0gYXdhaXQgZmFhc3RNb2R1bGUuY29zdFNuYXBzaG90KCk7XG5cbiAgICAgICAgY29uc3QgeyBlc3RpbWF0ZWRCaWxsZWRUaW1lIH0gPSBmYWFzdE1vZHVsZS5zdGF0cygpO1xuICAgICAgICB0LmlzKFxuICAgICAgICAgICAgKGVzdGltYXRlZEJpbGxlZFRpbWUubWVhbiAqIGVzdGltYXRlZEJpbGxlZFRpbWUuc2FtcGxlcykgLyAxMDAwLFxuICAgICAgICAgICAgY29zdHMuY29zdE1ldHJpY3MuZmluZChtID0+IG0ubmFtZSA9PT0gXCJmdW5jdGlvbkNhbGxEdXJhdGlvblwiKSEubWVhc3VyZWRcbiAgICAgICAgKTtcblxuICAgICAgICB0LnRydWUoY29zdHMuY29zdE1ldHJpY3MubGVuZ3RoID4gMSwgXCJjb3N0IG1ldHJpY3MgZXhpc3RcIik7XG4gICAgICAgIHQudHJ1ZShcbiAgICAgICAgICAgIGNvc3RzLmZpbmQoXCJmdW5jdGlvbkNhbGxSZXF1ZXN0c1wiKSEubWVhc3VyZWQgPT09IDEsXG4gICAgICAgICAgICBcImZ1bmN0aW9uQ2FsbFJlcXVlc3RzID09PSAxXCJcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3Qgb3V0cHV0ID0gY29zdHMudG9TdHJpbmcoKTtcbiAgICAgICAgY29uc3QgY3N2T3V0cHV0ID0gY29zdHMuY3N2KCk7XG4gICAgICAgIGxldCBoYXNQcmljZWRNZXRyaWMgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCBtZXRyaWMgb2YgY29zdHMuY29zdE1ldHJpY3MpIHtcbiAgICAgICAgICAgIHQucmVnZXgob3V0cHV0LCBuZXcgUmVnRXhwKG1ldHJpYy5uYW1lKSk7XG4gICAgICAgICAgICB0LnJlZ2V4KGNzdk91dHB1dCwgbmV3IFJlZ0V4cChtZXRyaWMubmFtZSkpO1xuICAgICAgICAgICAgaWYgKCFtZXRyaWMuaW5mb3JtYXRpb25hbE9ubHkpIHtcbiAgICAgICAgICAgICAgICB0LnRydWUobWV0cmljLmNvc3QoKSA+IDAsIGAke21ldHJpYy5uYW1lfS5jb3N0KCkgPiAwYCk7XG4gICAgICAgICAgICAgICAgdC50cnVlKG1ldHJpYy5tZWFzdXJlZCA+IDAsIGAke21ldHJpYy5uYW1lfS5tZWFzdXJlZCA+IDBgKTtcbiAgICAgICAgICAgICAgICB0LnRydWUobWV0cmljLnByaWNpbmcgPiAwLCBgJHttZXRyaWMubmFtZX0ucHJpY2luZyA+IDBgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhc1ByaWNlZE1ldHJpYyA9IHRydWU7XG4gICAgICAgICAgICB0LnRydWUobWV0cmljLmNvc3QoKSA8IDAuMDAwMDEsIGAke21ldHJpYy5uYW1lfS5jb3N0KCkgPCAwLjAwMDAxYCk7XG4gICAgICAgICAgICB0LnRydWUobWV0cmljLm5hbWUubGVuZ3RoID4gMCwgYCR7bWV0cmljLm5hbWV9Lmxlbmd0aCA+IDBgKTtcbiAgICAgICAgICAgIHQudHJ1ZShtZXRyaWMudW5pdC5sZW5ndGggPiAwLCBgJHttZXRyaWMubmFtZX0udW5pdC5sZW5ndGggPiAwYCk7XG4gICAgICAgICAgICB0LnRydWUoXG4gICAgICAgICAgICAgICAgbWV0cmljLmNvc3QoKSA9PT0gbWV0cmljLnByaWNpbmcgKiBtZXRyaWMubWVhc3VyZWQsXG4gICAgICAgICAgICAgICAgYCR7bWV0cmljLm5hbWV9IGNvc3QgaXMgY29tcHV0ZWQgY29ycmVjdGx5YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGFzUHJpY2VkTWV0cmljKSB7XG4gICAgICAgICAgICB0LnRydWUoY29zdHMudG90YWwoKSA+PSAwLCBgY29zdHMudG90YWwgPiAwIChoYXNQcmljZWRNZXRyaWMpYCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0LnRydWUoY29zdHMudG90YWwoKSA9PT0gMCwgYGNvc3RzLnRvdGFsID09PSAwICghaGFzUHJpY2VkTWV0cmljKWApO1xuICAgICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuY2xlYW51cCgpO1xuICAgIH1cbn1cblxuY29uc3QgeyBhd3NDb25maWd1cmF0aW9ucywgZ29vZ2xlQ29uZmlndXJhdGlvbnMgfSA9IENvc3RBbmFseXplcjtcbnRlc3QodGl0bGUoXCJhd3NcIiwgXCJjb3N0IGFuYWx5emVyXCIpLCB0ZXN0Q29zdEFuYWx5emVyLCBmaWx0ZXIoYXdzQ29uZmlndXJhdGlvbnMpKTtcbnRlc3QodGl0bGUoXCJnb29nbGVcIiwgXCJjb3N0IGFuYWx5emVyXCIpLCB0ZXN0Q29zdEFuYWx5emVyLCBmaWx0ZXIoZ29vZ2xlQ29uZmlndXJhdGlvbnMpKTtcblxuZm9yIChjb25zdCBwcm92aWRlciBvZiBwcm92aWRlcnMpIHtcbiAgICB0ZXN0KHRpdGxlKHByb3ZpZGVyLCBgY29zdCBlc3RpbWF0ZSBmb3IgYmFzaWMgY2FsbHNgKSwgdGVzdENvc3RzLCBwcm92aWRlcik7XG59XG4iXX0=