Skip to content

Commit bb8795f

Browse files
Merge pull request #231 from andrestoll/207-output-stats
Add optional input parameter to include all results in the output
2 parents 3af359f + ddc8297 commit bb8795f

File tree

4 files changed

+85
-12
lines changed

4 files changed

+85
-12
lines changed

README-INPUT-OUTPUT.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ The state machine accepts the following input parameters:
2323
* **discardTopBottom** (number between 0.0 and 0.4, by default is 0.2): By default, the state machine will discard the top/bottom 20% of "outliers" (the fastest and slowest), to filter out the effects of cold starts that would bias the overall averages. You can customize this parameter by providing a value between 0 and 0.4, with 0 meaning no results are discarded and 0.4 meaning that 40% of the top/bottom results are discarded (i.e. only 20% of the results are considered).
2424
* **sleepBetweenRunsMs** (integer) If provided, the time in milliseconds that the tuner function will sleep/wait after invoking your function, but before carrying out the Post-Processing step, should that be provided. This could be used if you have aggressive downstream rate limits you need to respect. By default this will be set to 0 and the function won't sleep between invocations. Setting this value will have no effect if running the invocations in parallel.
2525
* **disablePayloadLogs** (boolean) If provided and set to a truthy value, suppresses `payload` from error messages and logs. If `preProcessorARN` is provided, this also suppresses the output payload of the pre-processor.
26+
* **includeOutputResults** (boolean) If provided and set to true, the average cost and average duration for every power value configuration will be included in the state machine output.
2627

2728
## State machine configuration (at deployment time)
2829

@@ -151,7 +152,8 @@ The state machine will return the following output:
151152
"executionCost": 0.00045,
152153
"lambdaCost": 0.0005252,
153154
"visualization": "https://lambda-power-tuning.show/#<encoded_data>"
154-
}
155+
},
156+
"stats": [{ "averagePrice": 0.0000002083, "averageDuration": 2.9066666666666667, "value": 128}, ... ]
155157
}
156158
}
157159
```
@@ -164,4 +166,4 @@ More details on each value:
164166
* **results.stateMachine.executionCost**: the AWS Step Functions cost corresponding to this state machine execution (fixed value for "worst" case)
165167
* **results.stateMachine.lambdaCost**: the AWS Lambda cost corresponding to this state machine execution (depending on `num` and average execution time)
166168
* **results.stateMachine.visualization**: if you visit this autogenerated URL, you will be able to visualize and inspect average statistics about cost and performance; important note: average statistics are NOT shared with the server since all the data is encoded in the URL hash ([example](https://lambda-power-tuning.show/#gAAAAQACAAQABsAL;ZooQR4yvkUa/pQRGRC5zRaADHUVjOftE;QdWhOEMkoziDT5Q4xhiIOMYYiDi6RNc4)), which is available only client-side
167-
169+
* **results.stats**: the average duration and cost for every tested power value configuration (only included if `includeOutputResults` is set to a truthy value)

README.md

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ Please note that the input function will be executed in your AWS account - perfo
1818

1919
It's pretty simple and you can visually inspect each step in the AWS management console.
2020

21-
2221
![state-machine](imgs/state-machine-screenshot.png?raw=true)
2322

24-
2523
## What results can I expect from Lambda Power Tuning?
2624

2725
The state machine will generate a visualization of average cost and speed for each power configuration.
@@ -36,17 +34,14 @@ How to interpret the chart above: execution time goes from 35s with 128MB to les
3634

3735
How to interpret the chart above: execution time goes from 2.4s with 128MB to 300ms with 1GB, for the very same average cost.
3836

39-
40-
## How to deploy the state machine
37+
## How to deploy the state machine
4138

4239
There are a few options documented [here](README-DEPLOY.md).
4340

44-
4541
## How to execute the state machine
4642

4743
You can execute the state machine manually or programmatically, see the documentation [here](README-EXECUTE.md).
4844

49-
5045
## State Machine Input and Output
5146

5247
Here's a typical execution input with basic parameters:
@@ -81,7 +76,6 @@ The state machine output will look like this:
8176

8277
Full output documentation [here](README-INPUT-OUTPUT.md#user-content-state-machine-output).
8378

84-
8579
## Data visualization
8680

8781
You can visually inspect the tuning results to identify the optimal tradeoff between cost and performance.
@@ -106,7 +100,6 @@ Power Tuner UI repository: [mattymoomoo/aws-power-tuner-ui](https://github.com/m
106100

107101
[Here](README-ADVANCED.md) you can find out more about some advanced features of this project, its internals, and some considerations about security and execution cost.
108102

109-
110103
## CHANGELOG (SAR versioning)
111104

112105
From most recent to oldest, with major releases in bold:
@@ -157,7 +150,6 @@ From most recent to oldest, with major releases in bold:
157150
* ***1.0.0*** (2019-05-13): AWS SAM refactor (published on SAR)
158151
* *0.0.1* (2017-03-27): previous project (serverless framework)
159152

160-
161153
## Contributing
162154

163155
Feature requests and pull requests are more than welcome!

lambda/analyzer.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,19 @@ module.exports.handler = async(event, context) => {
2525
return console.log('[Dry-run] Skipping analysis');
2626
}
2727

28-
return findOptimalConfiguration(event);
28+
const result = findOptimalConfiguration(event);
29+
30+
if (!!event.includeOutputResults) {
31+
// add stats to final result
32+
result.stats = event.stats.map(stat => ({
33+
value: stat.value,
34+
averagePrice: stat.averagePrice,
35+
averageDuration: stat.averageDuration,
36+
// totalCost is omitted here
37+
}));
38+
}
39+
40+
return result;
2941
};
3042

3143
const getStrategy = (event) => {

test/unit/test-lambda.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,73 @@ describe('Lambda Functions', async() => {
16471647

16481648
});
16491649

1650+
it('should output all results if "includeOutputResults" is set to true', async() => {
1651+
const event = {
1652+
strategy: 'speed',
1653+
stats: [
1654+
{ value: '128', averagePrice: 100, averageDuration: 300, totalCost: 1 },
1655+
{ value: '256', averagePrice: 200, averageDuration: 200, totalCost: 1 },
1656+
{ value: '512', averagePrice: 300, averageDuration: 100, totalCost: 1 },
1657+
],
1658+
includeOutputResults: true,
1659+
};
1660+
1661+
const result = await invokeForSuccess(handler, event);
1662+
expect(result).to.be.an('object');
1663+
1664+
expect(result).to.have.property('stats');
1665+
expect(result.stats).to.eql(event.stats.map(stat => ({
1666+
value: stat.value,
1667+
averagePrice: stat.averagePrice,
1668+
averageDuration: stat.averageDuration
1669+
})));
1670+
1671+
expect(result.stats[0]).to.not.have.property('totalCost');
1672+
1673+
expect(result).to.have.property('power');
1674+
expect(result).to.have.property('cost');
1675+
expect(result).to.have.property('duration');
1676+
expect(result.stateMachine).to.be.an('object');
1677+
1678+
});
1679+
1680+
it('should not output any results if "includeOutputResults" is set to false', async() => {
1681+
const event = {
1682+
strategy: 'speed',
1683+
stats: [
1684+
{ value: '128', averagePrice: 100, averageDuration: 300, totalCost: 1 },
1685+
],
1686+
includeOutputResults: false,
1687+
};
1688+
1689+
const result = await invokeForSuccess(handler, event);
1690+
expect(result).to.be.an('object');
1691+
1692+
expect(result).to.not.have.property('stats');
1693+
expect(result).to.have.property('power');
1694+
expect(result).to.have.property('cost');
1695+
expect(result).to.have.property('duration');
1696+
expect(result.stateMachine).to.be.an('object');
1697+
});
1698+
1699+
it('should not output any results if "includeOutputResults" is not set', async() => {
1700+
const event = {
1701+
strategy: 'speed',
1702+
stats: [
1703+
{ value: '128', averagePrice: 100, averageDuration: 300, totalCost: 1 },
1704+
],
1705+
};
1706+
1707+
const result = await invokeForSuccess(handler, event);
1708+
expect(result).to.be.an('object');
1709+
1710+
expect(result).to.not.have.property('stats');
1711+
expect(result).to.have.property('power');
1712+
expect(result).to.have.property('cost');
1713+
expect(result).to.have.property('duration');
1714+
expect(result.stateMachine).to.be.an('object');
1715+
});
1716+
16501717
});
16511718

16521719
describe('optimizer', async() => {

0 commit comments

Comments
 (0)