-
Notifications
You must be signed in to change notification settings - Fork 421
Writing EMF metrics significantly increases lambda execution time #303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hey @tgip-work - thanks for the detailed issue. Question: Do you see the behaviour consistently in non-cold start executions? Last I remember checking fastjsonschema the cold start validation and serialisation was roughly 25ms, and single digit thereafter (mostly JSON Serialisation). If that however is happening even after cold start then it's a problem I'd like to prioritise to our next release (big one already). Thanks |
Hi @heitorlessa , thanks for your quick reply. |
Understood, thank you! While I don't think we can get to <1 ms because of how JSON works in python, uJSON could but that would be another dep.... we can surely decrease this time with a few perf improvements. I'll post an update this week on how far I get. Meantime, I've also finished this optimization that will be available in the next release on import times - Specially if you don't use Tracer (75% improvement). |
Initial perf test on my local machine (8 core, 32G RAM):
Fair to say we might be able reach <1ms indeed @tgip-work !! I'll experiment with native Python validation and keep you posted @pytest.mark.perf
def test_metrics_validation_sla(namespace, dimension, ninety_nine_metrics):
# GIVEN Metrics is initialized
my_metrics = Metrics(namespace=namespace)
my_metrics.add_dimension(**dimension)
# WHEN we add 99 metrics
for _metric in ninety_nine_metrics:
my_metrics.add_metric(**_metric)
with timing() as t:
my_metrics.serialize_metric_set()
elapsed = t()
if elapsed > METRICS_VALIDATION_SLA:
pytest.fail(f"Meh, can't let @tgip-work, at least below 10ms we should do it...: {elapsed}") |
Hi @heitorlessa : Yes, great work. This looks very promising! Happily looking forward for the next release :-) |
Turns out my test was wrong - I've converted from JSON Schema validation (~25ms) to Native Python (500-700usec), however, what was missing in the test was JSON Serialization. Adding JSON Serialization and printing the metrics makes us fail the goal of <1ms as we go from microseconds to ~7ms in total. IF we add ujson we easily reach <1ms, including other utilities that need JSON serialization like the upcoming idempotence will benefit from that, HOWEVER it'll increase the package size by 1M. I honestly think it's a great tradeoff, and that even means customers could benefit from that too since that will be installed in their Lambda functions -- Allow me to consult with the rest of the team to check on that. Worst case, we'll go from ~25ms to <10ms without having to even disable validation. Thanks |
Hi @heitorlessa, I am absolutely fine with reduced execution time if it is also possible to turn of validation as you already implemented as an option in your changes |
Actually no, lemme try that ;) thanks @tgip-work |
Yep not much, it reduces the len but the hog really is in the str conversion. I'm gonna stop chasing stars, commit what I've got, run in a function with low compute to see how much it actually brings besides perf tests, and swap with |
hahaha this is getting micro of microoptimization... removing static method calls and dictionary lookup before validation I can get down to 0.9usec-1.08ms now. I'll seriously stop, and commit this and try on the lowest function memory now :) |
Alright, here are the results with the lowest memory (128m) using the same 99 metrics -- @tgip-work @nmoutschen @michaelbrewer I'm pretty happy with it, and will not proceed with ujson as the underlying machine Lambda uses doesn't seem to make much use tbh - it could be different in other scenarios perhaps. I'll adjust the test SLA to take into account GitHub CI slower machines but I'd consider it solved... let me know otherwise @tgip-work :) BEFORE - Current public PowertoolsFastest Lambda execution according to X-Ray: 54ms All virtual users finished AFTER -- New Powertools with Lazy Loading and this PR optimizationFastest Lambda execution according to X-Ray: 2.2ms All virtual users finished AFTER - New optimizations + ujsonFastest Lambda execution according to X-Ray: 2.6ms All virtual users finished Details Load test with artillery using REST API + Lambda (could be even faster w/ HTTP API): Source code from aws_lambda_powertools import Metrics
# https://awslabs.github.io/aws-lambda-powertools-python/#features
metrics = Metrics(namespace="perftest", service="perftest")
@metrics.log_metrics
def lambda_handler(event, context):
for i in range(99):
metrics.add_metric(name=f"metric_{i}", value=1, unit="Count")
return {"statusCode": 200, "body": "hello world"} |
Merged :) It'll be available in the next release. Once #306 PR gets merged, we'll start drafting the next release ;) Thanks a lot for raising this with us @tgip-work and for the tip on json separator, much appreciated! |
This is now available in 1.11.0 - Literally just launched ;) 🎉 |
I am using the metrics functionality of the Lambda Powertools for generating custom Cloudwatch metrics (via writing EMF records into Cloudwatch logs).
The overall execution time of our Lambda functions has significantly increased since we are using the Powertools.
With "significantly" I mean approx. 50 to 100ms per metric on a 128 MB lambda function.
Expected Behavior
Adding metrics should only increase the execution time of a Lambda function by < 1ms per metric.
Current Behavior
Each metric added increases execution time by approx. 50 to 100ms on a Lambda function running with 128MB of RAM.
Possible Solution
I drilled down the code and guess that the schema validation is causing the performance issue. See [code] (https://github.com/awslabs/aws-lambda-powertools-python/blob/develop/aws_lambda_powertools/metrics/base.py#L214).
Possible solutions:
Steps to Reproduce (for bugs)
Environment
The text was updated successfully, but these errors were encountered: