AWS Lambda Runtime API

IMHO, there are two possibilities to address the GNUTLS/HTTPS issue

  • a/ compile GNUTls on Ubuntu with compile-time options to point to Amazon Linux's cacerts
  • b/ compile SWIFT on Amazon Linux.

I naively thought that a/ was easiest as I would deal with less dependencies issues. I am struggling on this since several days. GNUTls has so many dependencies and I am still blocked by a lib or other not being installed or correctly identified.

I tried b/ yesterday. The issue reported above by Jason is easy to work around. You need clang, cmake3 installed. I softlinked cmake -> cmake3 etc ... I am blocked further
The problem with the approcah above is that the yum install command can not find most of these dependencies :

No package uuid-dev available.
No package libicu-dev available.
No package icu-devtools available.
No package libbsd-dev available.
No package libedit-dev available.
No package libxml2-dev available.
No package libsqlite3-dev available.
Package swig-3.0.12-11.amzn2.0.3.x86_64 already installed and latest version
No package libpython-dev available.
No package libncurses5-dev available.
No package pkg-config available.
No package libblocksruntime-dev available.
No package libcurl4-openssl-dev available.
No package systemtap-sdt-dev available.

At this stage, I would love to receive help by someone use to build native Linux projects to solve teh dependency issues on a/ or b/

3 Likes

Wondering if it is a dead end on the Swift on AWS Lambda? I would like to help out on getting this to work. I have no idea where to start with this. Like all of you I can write the AWS Lambda Runtime API but getting it to work with API is not there

1 Like

Regarding the SSL path issue discussed above by @natanrolnik and @sebsto. One potential solution might be to make a small change in swift-corelibs-foundation to allow for setting the path with an environment variable rather than relying on the default location that the Ubuntu based docker image uses. There already is support for this feature but it is limited to Android.

#if os(Android) || os(Linux)
...
  if let caInfo = getenv("URLSessionCertificateAuthorityInfoFile")  {
...
    try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionCAINFO, caInfo).asError()
  }
#endif

We could change this line to also allow for Linux to configure the environment variable.

5 Likes

This would be even more convenient in a Lambda context than on Android- there it’s quite hard to provide the correct file path, in practice.

I've found a way to solve the HTTPS issue by using swift-nio 2.
I prepared an open-source framework https://github.com/swift-sprinter to support the development of the solution I've found.

Solving the HTTPS issue allows interacting with the AWS ecosystem.
I prepared documentation and three examples you can find here LambdaSwiftSprinter.

S3Test shows how to interact with an S3 bucket by using an early version of an open-source version of aws-sdk based on nio 2.

The project is in an early stage and it's open to collaboration and I hope someone will join me.

12 Likes

Wow, that sounds great! CC @georgebarnett, @tomerd, @kevints

2 Likes

Good news! Can't wait to use it myself :slight_smile:

It could be interesting once it's stable to do some benchmarks to see if it's a competitive option for production use.

Update:
Well we already have some elements there about general Swift performance.

@Damien_Petrilli , I like your idea.
I've opened an issue on the library, I would be very grateful if you can help me on this.


Feel free to open a new issue if this doesn't describe your idea.

You can consider the core LambdaSwiftSprinter package quite stable as it was ~100% tested (HelloWorld Example).

The unstable part is the one related to the nio 2.0 plugin and the aws-sdk as the related libraries are under development.

1 Like

I’ve been using your runtime for a couple of months, and absolutely loving it! I’m getting 100ms round-trip times for AWS API calls but I don’t know if this is an issue with the way I’m using the AWS SDK (the open source one on Github that you reference in your examples) or something else. Any notes you could add to the Readme on performance tips would be amazing! Again, really great project!!!

2 Likes

Hi @mr_j_tree - do you have any code to share? Have you tried out any logging or instrumentation around performance? What’s your code doing? Which services are you using? We’ll need more info to help diagnose.

Also if anyone here is at Re:invent this week and wants to connect and/or help move Swift on lambda forward let’s chat

Hi, I've been doing some investigation into this in the last week. You can see the results in this thread https://github.com/swift-aws/aws-sdk-swift/issues/202#issuecomment-560266370. Main things to extract from this are

  1. Most of the time is spent in the HTTP request part of the AWS API calls. This can be improved upon. The connection pool work that is happening on the async-http-client should improve things considerably if you are doing more than one api call in the lambda.
  2. cold starts hurt, really bad. The process of creating and signing a request takes over 100ms on the first call, subsequent calls it takes approx 1.5ms. If the lambda is warm the first call takes 1.5ms.
1 Like
  1. I got same results. I'm waiting for the connection pooling in async-http-client before publishing the full comparison with other languages.
  2. The cold start issue is mitigated by the provisioned concurrency of AWS Lambda announced yesterday: https://aws.amazon.com/about-aws/whats-new/2019/12/aws-lambda-announces-provisioned-concurrency/

Hi, I'm excited to share what I've been working on for the last two months or so.

Swift on Amazon Linux

I got Swift to compile on Amazon Linux 2. You can download the binaries from my website. If you want to see how the sausage is made, all scripts and Dockerfiles are public on GitHub. I would like to automate this process in so far that after a Swift release the whole release process is automated.

Swift on Amazon Linux Dockerimages

Another part of the amazonlinux-swift effort is to provide Dockerimages for your convenience at DockerHub to make compiling your Swift code for Amazon Linux 2 snappy.

Swift Lambda Layer

Even though I only made Swift compile on Amazon Linux 2, the libraries needed for running Swift are ABI compatible (pure luck, not official) with Amazon Linux 1. (Amazon Linux 1 is the operating system in which Lambdas without AWS provided runtime are executed.) Amazon Linux 1 is nearing end of life with support dropping on June 30, 2020. With this being said, AWS has to switch the underlying execution operating system to Amazon Linux 2 within the next 6 months. (They already have done that for node.js and Java)

Thanks to Swift running even on Amazon Linux 1, I have been able to create a Swift Amazon Linux Layer that links against Amazon Linux system libraries. The layer comes without any bootstrap and can be used in whatever way. You should bebe aware that you need an entrypoint (any executable named bootstrap) for execution. The Layers have already been uploaded in most AWS-Regions and are public for use in your Lambdas.

The scripts to create and distribute the Layers are part of the amazonlinux-swift project as well.

Since it is really just the Swift execution environment, it can be used with @Andrea-Scuderi's or @tonisuter's runtime. Since libFoundationNetworking links against the system's libcurl even https calls with NSURLSession are possible.

Swift-NIO opinionated AWS Lambda Runtime

I've created my own take on an AWS Lambda runtime called swift-lambda-runtime that builds on top of SwiftNIO and AsyncHTTPClient. The interface is Swift-NIO centric enabling the use of EventLoopFutures and an integration with swift-log. It includes a short tutorial on how to get your first Lambda running on AWS.

I'd be grateful for your feedback and hope that some of you enjoy this. I'm open to new contributors to this effort, just reach out.

29 Likes

This is awesome, all of it! Thank you for your work on this!

I don’t currently have a use-case but I’m very interested in the NIO part of this. Was thinking of starting work on a SwiftUI-style GraphQL Server but don’t have time right now

@GalCohen I have since realised what was going on with my AWS API calls from Lambda functions. I did not fully understand the way Lambda dynamically allocates CPU depending on your memory allocation. I was allocating the bare minimum of memory in order to save cost, without realising it was reducing available CPU time. Increasing memory allocation has got my DynamoDB API calls to perform at the expected speed... in the single digit millisecond range as advertised.

Cheers - lesson learned!

2 Likes

I just wanted to give you folks a small update on swift-lambda-runtime: With the latest release I added event types for six different source events:

  • Application Load Balancer handler
  • APIGateway handler
  • Cloudwatch Scheduled Events
  • DynamoDB Streams
  • SNS Messages
  • SQS Messages

So If you want to consume a SNS message in your lambda your code would look like this:

struct SNSBody: Codable {
  let name: String
  let whatevar: String
}

func handleSNS(event: SNS.Event, ctx: Context) -> EventLoopFuture<Void> {
  do {
    let message = event.records.first!.sns
    let body: SNSBody = try message.payload()
    
    // handle your message
    
    return ctx.eventLoop.makeSucceededFuture(Void())
  }
  catch {
    return ctx.eventLoop.makeFailedFuture(error)
  }
}

// some more setup

let runtime = try LambdaRuntime.createRuntime(eventLoopGroup: group, handler: handleSNS)

You can get an idea of how to use the events by looking at my example: EventSources. In this package you can also find a template.yaml that can give you an idea on how to setup your surroundings with aws-sam.

If you have any questions please reach out: I'm @fabianfett on twitter or just open a GitHub issue.

9 Likes

Just for completeness and information of everyone interested in Lambda:

I started a discussion about how a Linux distribution other than Ubuntu can be officially supported by Swift: Official platform support for other Linux Distributions (and a case for Amazon Linux 2)

Maybe you are interested in this?

2 Likes

Hi all,

I finally completed the performance evaluation of Swift on AWS Lambda, I’ve published all the results in this article

I compared Swift performances not only among different languages but also between Ubuntu and the Amazon Linux 2 build provided by @fabianfett.

It’s well known that the overall performance of lambda is dependent on the code size and the allocated memory (and vCPU).

I compared the performance of lambda with the same amount of Memory and vCPU using a basic HelloWorld example.

Refer to this article to better understand what is Cold and Warm start and how AWS Lambda works https://dev.to/sosnowski/anatomy-of-aws-lambda-1i1e.

AWS Swift vs other Languages

  • Code size gives an advantage to all the runtimes already supported by AWS
  • Cold Start for Swift is ~190ms, Go ~75ms, Python ~127ms, NodeJS ~128ms
  • Warm Start for Swift is ~1.19ms, Go ~0.44ms, Python 1.34ms, NodeJS ~1.06ms

With a small penalty on cold start the performance of Swift is comparable to Python and NodeJS

AWS Swift Lambda Layer Ubuntu vs Amazon Linux 2

  • The Amazon Linux 2 custom run time is around ~20MB and the Ubuntu custom runtime is ~40MB
  • The reduced size of code gives at Cold start advantage of ~140ms to Amazon Linux 2 [Amazon Linux 2 (~190 ms) vs Ubuntu (~329 ms)]
  • At warm start there is no substantial difference between Amazon Linux 2 and Ubuntu.

The small penalty paid by Ubuntu is compensated by a more stable and certified building pipeline.

Swift with libCURL vs AsyncHTTPClient (Swift NIO)

Swift-Sprinter vs Swift-NIO opinionated AWS Lambda Runtime

  • Both framework use Swift NIO
  • Swift Sprinter performs slightly better with a difference of ~0.20 ms at warm start
  • On cold start it depends on the runtime version.
  • Swift Sprinter can be built with Ubuntu and Amazon Linux, Swift-NIO opinionated can be built only with Amazon Linux 2

Conclusions

Swift using AsyncHTTPClient NIO with connection Pooling shows good performance on AWS Lambda compared to most popular languages.

The only advantage of using Amazon Linux 2 rather than Ubuntu is given by ~140ms on cold start, when there is no much difference at warm start.

In the wait to have a stable Amazon Linux 2 swift version, we should note that this advantage is not so huge and can be mitigated using provisioned concurrency.

7 Likes

Thanks for the interesting insight, I just read the results but it seems like a good enough spot to be in.

Terms of Service

Privacy Policy

Cookie Policy