DEV Community

Cover image for Deep dive: finding the optimal resources allocation for your Lambda functions

Deep dive: finding the optimal resources allocation for your Lambda functions

Alex Casalboni on September 17, 2020

Building with a serverless mindset brings many benefits, from high availability to resiliency, pay for value, managed operational excellence, and m...
Collapse
 
rosswilliams profile image
rosswilliams • Edited

I often see different numbers than yours when going from 128 to 256 (or other doubling of power) I get a more than halving of execution time. But I can’t figure out why this is true. Is it because of the scheduler, CPU cache, or bandwidth?

Have you seen these cases, and if so how do you explain it.

Edit: most of my lambdas are a DynamoDB query, Update, and value return.

Collapse
 
alexcasalboni profile image
Alex Casalboni

Hi Ross, thanks for asking!

For DDB queries, it should be a mix of better CPU and better I/O throughput. It is quite common to see such an improvement when you double your function's power - it looks exactly like pattern 5 in the article :)

Collapse
 
rosswilliams profile image
rosswilliams

Yes thanks! I think your example for 512MB goes below 100ms, so its actually showing a bigger time reduction, but not reflected in the price information. Glad it’s not just me seeing this pattern

Collapse
 
ricardo1980 profile image
Ricardo Ruiz Lopez

Great article! Thanks a lot.
When using amplify, we have cloud formation templates generated by amplify that we can customised if we want (very often I do that to add new permissions).
How should I hardcode the power I need in this scenario? Because my entire system should be described using these templates as far as I know.
Thanks a lot.

Collapse
 
alexcasalboni profile image
Alex Casalboni

Hi Ricardo, very good question :)

You should be able to edit (or add) the MemorySize property of your function. It's always an integer value in MB and you can customize it for each individual function. CloudFormation doc here.

I don't think you can do this with Amplify templates, but when using AWS SAM you can also customize the memory of all the functions in your template using the Globals section.

Collapse
 
rosswilliams profile image
rosswilliams

With amplify your can directly modify the cloud formation template for lambda functions and the changes will be preserved

Collapse
 
germanviscuso profile image
German Viscuso

Hi Alex. Awesome article! Given the obvious benefits, why is not AWS Lambda doing this optimization automatically for you (via opt-in for example)?

Collapse
 
alexcasalboni profile image
Alex Casalboni

Very good question, German :)

I can think of two good reasons why this is hard to provide as a managed solution:

1) you need to provide a valid input event for power-tuning, as every function requires its own specific payload; while this is something that can be automated, it's also very function-specific and domain-specific (Alexa skill vs S3 event vs Kinesis stream vs HTTP request)

2) power-tuning requires executing your functions in a real environment, with real downstream dependencies (databases, 3rd-party API's, legacy systems, etc.) so you need to be aware of those downstream services and prepare them for the load, otherwise you'll get noisy or inconsistent results

But never say never :)

Collapse
 
abbadev profile image
Abdulla T

This is an awesome article and a brilliant deep dive. You can't imagine the number of debates I have had with my teammates when trying to select the best memory for our lambda functions.

Collapse
 
alexcasalboni profile image
Alex Casalboni

Thanks πŸ™ I'm glad it was a useful read for you (and your team)

Collapse
 
adamcoster profile image
Adam Coster

I feel like I'm missing something here. The cost of lambda goes up roughly linearly with memory, as does performance, so without the 100ms binning of billing you'd expect things to more or less break even. Because of the 100ms step though it's generally better (for cost) to use less power. In your first example the billed cost actually goes up by 30% even though the time goes down by 30%. For fast functions (on the order of a small number of 100ms) it will generally be cheaper to use as little power as possible, because the 100ms billing rounding error creates substantial cost unless 100ms is small compared to execution time.

Collapse
 
alexcasalboni profile image
Alex Casalboni

Because of the 100ms step though it's generally better (for cost) to use less power.

This depends a lot on the use case. Some of the workload categories I've described do benefit from using more power (especially the CPU-bound ones) since it often results in lower average cost too.

In your first example the billed cost actually goes up by 30% even though the time goes down by 30%.

Thanks, I think you've found a typo in my first example. As I've reshaped that example a few times, in the latest version average cost is not constant anymore. The idea was that often you can double power and half execution time, resulting in the same average execution cost. I'll fix it now.

For fast functions (on the order of a small number of 100ms) it will generally be cheaper to use as little power as possible...

I think this is good advise only if you don't care about performance (i.e. for most asynchronous executions, where nobody is waiting for a response).

Collapse
 
nikuamit profile image
Amit Kumar Sahu

Well explained. Great article , Alex. Thanks for putting this..

Some comments have been hidden by the post's author - find out more