Demonstrating Memory Behavior for AWS Lambda Function Freezing

AWS indicates that when a function is executed, there are some things that get leftover between runs. The execution environment, which AWS indicates is a container model, contains everything necessary to run the function. After a function is invoked for the first time, it will “freeze” this environment such that it can quickly be called a second time, which will help improve the performance of subsequent runs by avoiding the initialization step of getting your code out into this execution environment. This container reuse, however, can be a benefit or a downside depending on how you write your function. One of these is related to the memory usage of an execution environment.

Say you have the following code:

'use strict';

var arrayA = [];
var arrayB = [];

module.exports.test = (event, context, callback) => {
  var arrayC = [];
  var arrayD = [];

  arrayA.push("A");
  arrayB.push("B");
  arrayC.push("C");
  arrayD.push("D");

  console.log("Array A:", arrayA);
  console.log("Array B:", arrayB);
  console.log("Array C:", arrayC);
  console.log("Array D:", arrayD);

  arrayA = [];
  arrayC = [];

  callback(null);
};

We initialize 2 empty arrays, arrayA and arrayB, outside of the handler. When the function is run, these two arrays will remain in memory when the function is frozen. Inside of the hander we’ve got 2 more empty arrays, arrayC and arrayD. During the execution of the function we simply push a string item to it and for testing, we clear our arrays arrayA and arrayC. Let’s look at what this does when AWS invokes this function three times:

serverless-freezing-demonstration % serverless invoke -f test -s dev -l
null
--------------------------------------------------------------------
START RequestId: 778bcf95-a285-11e6-aa5a Version: $LATEST
2016-11-04 07:54:40.248	778bcf95-a285-11e6-aa5a	Array A: [ 'A' ]
2016-11-04 07:54:40.284	778bcf95-a285-11e6-aa5a	Array B: [ 'B' ]
2016-11-04 07:54:40.284	778bcf95-a285-11e6-aa5a	Array C: [ 'C' ]
2016-11-04 07:54:40.284	778bcf95-a285-11e6-aa5a	Array D: [ 'D' ]
END RequestId: 778bcf95-a285-11e6-aa5a
REPORT RequestId: 778bcf95-a285-11e6-aa5a	Duration: 37.54 ms	Billed Duration: 100 ms 	Memory Size: 128 MB	Max Memory Used: 14 MB

serverless-freezing-demonstration % serverless invoke -f test -s dev -l
null
--------------------------------------------------------------------
START RequestId: 7b760204-a285-11e6-bf4a Version: $LATEST
2016-11-04 07:54:46.714 7b760204-a285-11e6-bf4a	Array A: [ 'A' ]
2016-11-04 07:54:46.714 7b760204-a285-11e6-bf4a	Array B: [ 'B', 'B' ]
2016-11-04 07:54:46.714 7b760204-a285-11e6-bf4a	Array C: [ 'C' ]
2016-11-04 07:54:46.714 7b760204-a285-11e6-bf4a	Array D: [ 'D' ]
END RequestId: 7b760204-a285-11e6-bf4a
REPORT RequestId: 7b760204-a285-11e6-bf4a	Duration: 0.68 ms	Billed Duration: 100 ms 	Memory Size: 128 MB	Max Memory Used: 14 MB

serverless-freezing-demonstration % serverless invoke -f test -s dev -l
null
--------------------------------------------------------------------
START RequestId: 7ecbbbed-a285-11e6-99ff Version: $LATEST
2016-11-04 07:54:52.288 7ecbbbed-a285-11e6-99ff	Array A: [ 'A' ]
2016-11-04 07:54:52.289 7ecbbbed-a285-11e6-99ff	Array B: [ 'B', 'B', 'B' ]
2016-11-04 07:54:52.289 7ecbbbed-a285-11e6-99ff	Array C: [ 'C' ]
2016-11-04 07:54:52.289 7ecbbbed-a285-11e6-99ff	Array D: [ 'D' ]
END RequestId: 7ecbbbed-a285-11e6-99ff
REPORT RequestId: 7ecbbbed-a285-11e6-99ff	Duration: 0.52 ms	Billed Duration: 100 ms 	Memory Size: 128 MB	Max Memory Used: 14 MB

You’ll notice in the first run, we have pushed one object to all four arrays. In the second run, arrayB has a second object in the array, and in the third run, a third object is added to arrayB. arrayA doesn’t exhibit this behavior because it is reinitialized to an empty array prior to stopping the function. arrayC and arrayD technically get reinitialized at every run.

With this small demo, we can see some value and some potential headache when created incorrectly. This could be a great strategy if we need to do something expensive, such as setup a database connection. Inside of the handler, we can call upon that object to reconnect to the database without needing to go through the heavy lifting every single time.

To avoid leaking memory, we would want to ensure as much data as possible is located within the handler to minimize problems.

John T Skarbek

John T Skarbek
Im an Infrastructure Engineer at CA Technologies in the Agile Business Unit. Reading and using the latest and greatest of technology is what I want to be doing. Blogging is not something I do on any regular basis (and it shows).

Openshift v3 Deployment Strategy

Openshift version 3, or Openshift Origin, has been a fantastic Platform as aService to play with. The team I work on have come up with a...… Continue reading

Haproxy URL Rewrite Logging Double Take

Published on May 29, 2015

Haproxy Quick ACL Testing

Published on May 29, 2015