Эксперт по Java и любитель AWS Александр Филичкин опубликовал интересные бенчмарки функций AWS Lambda на всех языках программирования, которые официально поддерживаются (плюс ещё два).
AWS Lambda — услуга AWS, которая обеспечивает событийно-ориентированные вычисления. Она активируется в ответ на заданное событие — и автоматически привлекает все необходимые ресурсы для обработки запроса. Другими словами, она позволяет запускать код без выделения серверов и управления ими (бессерверная модель). Вы платите только за фактическое время вычисления.
AWS Lambda официально поддерживает NodeJS, Python, Go, Ruby, .Net и Java, но косвенно поддерживаются и другие языки. Александр добавил к тестам Rust и GraalVM.
Все тесты выполнялись в сентябре 2021 года (репозиторий на Github) в конвейере API-Gateway → AWS Lambda → DynamoDb (в базе делается POST с сохранением книги).
Например, вот код лямбды на Python:
С холодного старта все языки показали низкую задержку, кроме Java и .Net, причём Java вообще не смогла стартовать на минимальном объёме памяти 128 МБ. Почти везде победил Rust, кроме минимальной конфигурации, где первенствовал Python.
Нормальный тест с горячего старта включал в себя 15 000 последовательных запросов к каждой лямбде. По итогу фиксировалось среднее время выполнения на всех конфигурациях памяти, а также максимальная продолжительность выполнения (максимум миллисекунд на каждую минуту) на 256 МБ.
Каждый раз выполнение лямбды занимает разное время. Например, Node.js сначала выполняется медленно, а потом разгоняется благодаря JIT-оптимизации.
Python показывает стабильную производительность, а Ruby ведёт себя очень странно: среднее время выполнения постоянно растёт (похоже на утечку памяти или баг в коде). Для сравнения, у .Net первая тысяча вызовов выполняется медленно, а потом производительность чрезвычайно высокая. Аналогичная картину у Go и Java. А вот GraalVM и особенно Rust показывают очень высокую производительность с самого старта.
Вот среднее время выполнения для всех языков после трёх прогонов по 5000 вызовов с получасовой задержкой между тестами на 256 МБ:
Интересно, что на 128 МБ картина кардинально иная:
В итоге абсолютными победителями соревнования стали Go и Rust, показавшие великолепную производительность в роли лямбда-функции AWS. Такую же производительность продемонстрировал .Net, но только после тысячи запросов. GraalVM почти дотянул до них, но не осилил конфигурацию с минимальной памятью. С Java случилось что-то странное, почему-то не сработала JIT-оптимизация компилятора C2 (возможно, AWS её отключила). У Python хорошая производительность, кроме 128 МБ, у Ruby почти такая же, но происходит некоторое замедление через 20 минут работы (после 15 тыс. вызовов). Наконец, самым медленным стал NodeJS, хотя он постепенно ускоряется, но даже на своём максимуме работает медленнее всех.
AWS Lambda — услуга AWS, которая обеспечивает событийно-ориентированные вычисления. Она активируется в ответ на заданное событие — и автоматически привлекает все необходимые ресурсы для обработки запроса. Другими словами, она позволяет запускать код без выделения серверов и управления ими (бессерверная модель). Вы платите только за фактическое время вычисления.
AWS Lambda официально поддерживает NodeJS, Python, Go, Ruby, .Net и Java, но косвенно поддерживаются и другие языки. Александр добавил к тестам Rust и GraalVM.
Все тесты выполнялись в сентябре 2021 года (репозиторий на Github) в конвейере API-Gateway → AWS Lambda → DynamoDb (в базе делается POST с сохранением книги).
Например, вот код лямбды на Python:
import json
import uuid
import boto3
dynamodb = boto3.resource('dynamodb',region_name='us-east-2')
table = dynamodb.Table('book')
def create(event, context):
data = json.loads(event['body'])
item = {
'id': str(uuid.uuid1()),
'author': data['author'],
'name': data['name'],
}
# write the db
table.put_item(Item=item)
# create a response
response = {
"statusCode": 201,
"body": json.dumps(item)
}
return response
С холодного старта все языки показали низкую задержку, кроме Java и .Net, причём Java вообще не смогла стартовать на минимальном объёме памяти 128 МБ. Почти везде победил Rust, кроме минимальной конфигурации, где первенствовал Python.
Нормальный тест с горячего старта включал в себя 15 000 последовательных запросов к каждой лямбде. По итогу фиксировалось среднее время выполнения на всех конфигурациях памяти, а также максимальная продолжительность выполнения (максимум миллисекунд на каждую минуту) на 256 МБ.
Каждый раз выполнение лямбды занимает разное время. Например, Node.js сначала выполняется медленно, а потом разгоняется благодаря JIT-оптимизации.
Python показывает стабильную производительность, а Ruby ведёт себя очень странно: среднее время выполнения постоянно растёт (похоже на утечку памяти или баг в коде). Для сравнения, у .Net первая тысяча вызовов выполняется медленно, а потом производительность чрезвычайно высокая. Аналогичная картину у Go и Java. А вот GraalVM и особенно Rust показывают очень высокую производительность с самого старта.
Вот среднее время выполнения для всех языков после трёх прогонов по 5000 вызовов с получасовой задержкой между тестами на 256 МБ:
Интересно, что на 128 МБ картина кардинально иная:
В итоге абсолютными победителями соревнования стали Go и Rust, показавшие великолепную производительность в роли лямбда-функции AWS. Такую же производительность продемонстрировал .Net, но только после тысячи запросов. GraalVM почти дотянул до них, но не осилил конфигурацию с минимальной памятью. С Java случилось что-то странное, почему-то не сработала JIT-оптимизация компилятора C2 (возможно, AWS её отключила). У Python хорошая производительность, кроме 128 МБ, у Ruby почти такая же, но происходит некоторое замедление через 20 минут работы (после 15 тыс. вызовов). Наконец, самым медленным стал NodeJS, хотя он постепенно ускоряется, но даже на своём максимуме работает медленнее всех.