Aws-lambda-dotnet: Производительность C# Lambda по сравнению с Node по сравнению с Python

Созданный на 12 дек. 2016  ·  35Комментарии  ·  Источник: aws/aws-lambda-dotnet

Первый. Спасибо за перенос C# в Lambda! Я люблю это!

Я провел быстрый и грязный тест производительности, чтобы сравнить, насколько быстро могут вызываться различные лямбда-функции. Все тесты проводились путем отправки строки "foo" качестве входных данных для каждой соответствующей функции с помощью консоли AWS. Тест был очень простым: я просто несколько раз нажимал кнопку Test в консоли AWS Lambda и выбирал типичный отчет журнала.

Питон

REPORT RequestId: 6c2026c2-c028-11e6-aecf-116ec5921e69    Duration: 0.20 ms    Billed Duration: 100 ms     Memory Size: 128 MB    Max Memory Used: 15 MB

Javascript/NodeJS

REPORT RequestId: 10a2ac96-c028-11e6-b5eb-978ea2c1c2bd    Duration: 0.27 ms    Billed Duration: 100 ms     Memory Size: 128 MB    Max Memory Used: 16 MB

С#

REPORT RequestId: d9afca33-c028-11e6-99df-0f93927a56a6    Duration: 0.85 ms    Billed Duration: 100 ms     Memory Size: 256 MB    Max Memory Used: 42 MB

Функции были развернуты в us-east-1 с соответствующими настройками по умолчанию. Функция C# была развернута с использованием dotnet lambda deploy-function . Функции Node и Python были развернуты с использованием примера кода HelloWorld для каждого соответствующего языка и изменения реализации, чтобы простая строка принималась и преобразовывалась в верхний регистр.

Вы можете найти код здесь: https://github.com/LambdaSharp/LambdaPerformance

Могу ли я что-нибудь сделать, чтобы оптимизировать время вызова на моей стороне? Это то, над чем вы все еще работаете? Просто интересно состояние. Спасибо!

guidance

Самый полезный комментарий

@yunspace ересь! :)

C# Lambda All Things!

Все 35 Комментарий

Производительность — это то, над чем мы всегда будем продолжать работать с Lambda и всеми поддерживаемыми средами выполнения. У каждого языка есть свои сильные и слабые стороны, поэтому у нас такие веселые языковые войны :)

Этот тест просто измеряет время запуска среды выполнения языка, что является чем-то вроде того, что динамические языки, такие как Node.js и Python, всегда были быстрее по сравнению со статическими языками, такими как C# и Java, из-за отсутствия проверки типов и более ленивой загрузки зависимостей.

Извините, я не хотел закрывать его. Смело продолжайте разговор.

Спасибо, что держите это открытым. Это не критика, а основа для открытой дискуссии.

В своем ответе вы упомянули, что тест измеряет время запуска языка. Я хотел бы внести больше ясности в это утверждение. Я думал, что при первом обращении приложение инициализируется (при необходимости), а затем запускается, но при последующих обращениях оно разогревается. Если он запускается каждый раз, то нет смысла перемещать однократный код (например, чтение значений конфигурации) в конструктор класса обработчика, поскольку он все равно создается при каждом вызове. Я не так понял из вашей презентации re:Invent. Не могли бы вы уточнить. Спасибо!

Просто чтобы подтвердить свое понимание, я перечитал, как работает контейнер Lambda здесь: http://docs.aws.amazon.com/lambda/latest/dg/lambda-introduction.html.

@bjorg @normj документация в этом отношении довольно расплывчата :(
Я предоставил ниже отзыв и надеюсь, что он будет разъяснен

  • 'Как мы можем сделать его лучше?
    быть точным в том, где фактическое время для «некоторого времени» можно найти для утверждения: «AWS Lambda поддерживает контейнер в течение некоторого времени в ожидании другого вызова функции Lambda».
  • Что ты пытаешься сделать?
    определить, сколько времени действительно происходит повторное использование контейнера, чтобы предсказать производительность

@bjorg то, что вы здесь разместили, не является _холодным временем запуска Lambda_. Но _теплое время отклика_.

Когда функция C# впервые запускается с нуля, это может занять до нескольких сотен миллисекунд (в моем случае это 500 мс). После того, как он прогреется, он останется в живых и будет обслуживать запросы с большей скоростью, аналогичной той, которую вы опубликовали (в моем случае это было от 0,9 до 1 мс). В конце концов, он умрет в конце своего жизненного цикла, или произойдет автомасштабирование, и запустится больше холодных лямбда-выражений. Чтобы узнать время запуска, подождите 15 минут или около того, затем нажмите «Тест».

Так что да, вы все еще помещаете вещи в конструкторы. Потому что вы не получаете совершенно новую лямбду каждый раз, когда нажимаете «Тест». Но вы получите совершенно новую лямбду, если будете щелкать только раз в час.

С точки зрения оптимизации, для _времени холодного запуска_ вы можете:

  1. убедитесь, что у вас всегда есть поступающие запросы, 24x7, чтобы ваши лямбды всегда были теплыми
  2. настройте периодический пинг на вашей лямбде (либо расписания облачных часов, либо newrelic, либо что-то еще), чтобы ваши лямбды всегда были теплыми.

Оптимизация _теплого времени отклика_ действительно не имеет особого смысла:

  1. общепринятое время отклика человека составляет 200 мс
  2. менее 1 мс на самом деле довольно хорошо. Вы редко получите эту ставку за пределами helloworld или toUpper .
  3. Если вы поместите шлюз API перед своей лямбдой и выставите HTTP-вызовы миру. Среднее время кэшированного вызова из Интернета составляет около 50 мс.
  4. AWS в любом случае выставляет вам счет с интервалом в 100 мс.
  5. 0,85 мс, вероятно, близко к производительности обычного кода C#. Попробуйте запустить свою функцию на своем компьютере внутри основного метода и посмотрите.

Также не путайте производительность со временем отклика. Тот факт, что Node отвечает за 20 мс, когда вы последовательно нажимаете вручную, не означает, что он будет вести себя так же, когда в секунду поступает 100 000 автоматических запросов и увеличивается с каждой секундой. Проведите параллелизм и нагрузочные тесты. Вы можете обнаружить, что многопоточные языки, такие как Java или C#, могут обрабатывать больше запросов в секунду под нагрузкой. На самом деле я где-то видел лямбда-статистику: Python = самый быстрый холодный запуск, Java = самый быстрый теплый запрос в секунду, но сейчас не могу найти.

В любом случае, это должно ответить на ваш вопрос, надеюсь.

нашел обсуждение, содержащее бенчмарк https://www.quora.com/Which-language-better-suits-for-AWS-Lambda

@yunspace , спасибо за подробное описание. Меня больше всего интересует, как текущая реализация .NET Core маршалирует данные из необработанного внутреннего вызова в обработчик C#. Поскольку обработчик может различаться по сигнатуре (как по типу, так и по количеству аргументов), я бы предположил, что он вызывается через отражение. Итак, мой вопрос в основном заключался в том, есть ли способ получить вызов, не затрагивая уровень маршалинга. Например, подпись Foo(Stream, ILambdaContext) может быть предопределенным шаблоном обработчика, который обходит любую логику преобразования полезной нагрузки в экземпляр POCO.

К сожалению, код вызова недоступен для проверки, поэтому я не знаю, можно ли его еще оптимизировать. Я ожидаю, что теплый вызов будет очень близок по производительности к этим другим средам выполнения.

Для несортировки необработанных входных данных JSON в POCO лямбда- Amazon.Lambda.Serialization.Json, основанный на популярном Newtownsoft Json.Net. Но вы можете заменить эту реализацию по умолчанию своим собственным сериализатором. См. раздел « Обработка стандартных типов данных».

Я понимаю что ты имеешь ввиду. Большинство сериализаторов (включая Json.Net) используют медленное отражение. Чтобы доказать эту теорию, я полагаю, вы могли бы посмотреть, дает ли Foo(Stream, ILambdaContext) лучшее время отклика для теплых вызовов. И если это так, то, вероятно, стоит создать собственный сериализатор клиентов для строк и POCO.

На самом деле я говорил не о десериализаторе данных, а о методе, вызывающем лямбда-обработчик. Поскольку лямбда-обработчик может иметь разные сигнатуры (как по типу, так и по количеству аргументов), вызывающий его метод должен полагаться на отражение. Насколько я знаю, невозможно написать обработчик лямбда таким образом, чтобы обойти этот механизм удобства.

Недавно я провел некоторое тестирование и обнаружил, что сериализатор действительно не оказывает большого влияния. Фактически, удаляя почти все движущиеся части и возвращая статические данные или просто пустые потоки, кажется, что лучшее, что вы можете получить, — это около 0,85 мс на теплой функции. Я подозреваю, что код, который вызывает функцию C#, скорее всего, виноват, и кажется, что к нему может обращаться только команда лямбда (

Для всех других сред выполнения, включая Java, вы можете получить от 0,22 до 0,30 мс для теплой функции. По сути, это означает, что накладные расходы на вызов лямбда в 3-4 раза хуже для С#.

Хотя я согласен с тем, что это не говорит всей истории, поскольку C#, вероятно, будет быстрее выполнять реальную работу, эти накладные расходы фреймворка заслуживают того, чтобы на них обратить внимание. Я предполагаю, что отчасти это можно объяснить тем, что он новый, а производительность не была самым большим приоритетом. Также может быть виновато чрезмерное использование отражения без какого-либо кэширования.

Я также подозреваю, что это связано с ранним кодом. Я бы хотел, чтобы мы могли увидеть, как это выглядит, чтобы мы могли помочь в его оптимизации. В качестве альтернативы, наличие крючка более низкого уровня для экспериментов также может помочь.

Я тоже хочу, чтобы мы могли помочь. Я на грани, просто жду, когда ядро ​​C# заработает множеством способов. Это решающий определяющий фактор между Azure и Amazon. Безсерверный подход C# намного лучше, чем поддержка нескольких машин EC2 с обновлениями Windows, проверками производительности, обновлениями SQL и т. д. Поддержание этих сред в актуальном состоянии для клиентов требует почти полного рабочего дня.

Безсерверный подход C# является более экономичным, гораздо менее трудоемким, автоматически масштабируемым и повторно используемым.

Единственная другая нерешенная проблема - это экономичный масштабируемый подход RDC сейчас :-)

Я передал эту тему сервисной команде для проверки. В основном я поддерживаю клиентские инструменты, такие как эти библиотеки и интеграцию с Visual Studio, поэтому я не могу много говорить о том, что происходит на стороне сервиса. Я могу сказать вам в своем ограниченном просмотре кода службы, что использование отражения оптимизировано, но всегда есть другие факторы, на которые следует обратить внимание.

@genifycom Насколько я понимаю, этот поток отслеживает разницу в производительности в 0,5 мс для теплого запуска по сравнению с другими средами выполнения. Поскольку Lambda выставляет счета с шагом 100 мс, блокирует ли эта разница в производительности ваше использование? Я не пытаюсь преуменьшить важность понимания сути этого несоответствия, но большая область, над которой сейчас работает команда Lambda, — это время холодного запуска.

Чтобы уточнить, это не останавливает нас от принятия C# Lambda (или LambdaSharp, как мы его окрестили). Это больше повод для гордости. :)

Полностью понимаю!

Не уверен, что это правильное место, но в настоящее время мы создаем веб-сервер на C #, и у нас есть время холодного запуска в несколько секунд, иногда до десяти или даже больше. Хотя после первого удара все в порядке. Это все еще нормально для нетривиального проекта C#, или мы можем что-то сделать, чтобы уменьшить это? Нам нравится работать в нашей знакомой экосистеме .NET, но это доставляет нам некоторые головные боли.

Я предполагаю, что это связано с внешними пакетами, которые мы включили в проект, и с тем, как они обрабатываются Amazon во время холодного запуска, потому что с пустым проектом дела обстоят намного лучше. Я надеялся, что кто-то может пролить свет на это.

@normj Есть ли новости о проблемах с производительностью, которые мы наблюдаем?

@SpoonOfDoom Вы видели совет бить его каждые 10 минут или около того? Это довольно стандартная практика в .Net навсегда, еще в 90-х годах это сделало мой хостинг-бизнес самым быстрым, зная, что в то время как никто другой - Но это очень распространено сейчас и даже такие распространенные инструменты, как этот - https://www.iis.net/downloads /microsoft/application-initialization — рекомендуемые. Lambda изменяет модель затрат, но в какой-то степени сталкивается с теми же проблемами, независимо от того, как они ее проектируют.

@bitshop Это то, чем мы сейчас занимаемся. Мы вызываем все раз в 10 минут, и в большинстве случаев это помогает. Но у нас все еще есть некоторые всплески каждые несколько часов, когда мы снова сталкиваемся с холодным запуском — кажется, что экземпляры AWS, на которых запущены .Net Lambdas, имеют максимальное время жизни, а затем используется новый, независимо от текущего горячего/холодного статуса? Я не уверен.
Кажется странным решение Amazon не давать разработчикам возможности полностью защититься от этого (по крайней мере, за определенную цену). Конечно, сейчас мы сталкиваемся с пиком только каждые несколько часов, но если его достигает клиент, а не наш скрипт, клиент все равно будет раздражен и воспримет наше приложение как ненадежное и/или медленное.

@yunspace Похоже, что лямбда-функции шаблона по-прежнему потребуется время холодного запуска более 2000 мс.
REPORT RequestId: d1e5f56c-0ea9-11e7-bb5d-bb039f76a793 Duration: 2120.69 ms Billed Duration: 2200 ms

@normj Что я сделал не так?

Обновление: я обнаружил, что если функция принимает вход string , время запуска будет ~ 800 мс, но если я на самом деле выбрал для нее другой тип, оно станет более 2000 мс.

    // 800ms
    public string FunctionHandler(string input, ILambdaContext context)

    // 2000ms, Request being the other object type
    public string FunctionHandler(Request input, ILambdaContext context)

У меня время холодного запуска ~ 21 секунда в 128 МБ для двух разных лямба-функций на С#, обе получают SNS. Я получаю примерно то же время с триггером S3 put по сравнению с SNS. Теплый, это ~2 секунды.

Если я увеличиваю память до 256 МБ, я вижу, что время трески падает примерно до ~ 10 секунд и т. Д.

Журналы Lambda показывают, что я использую 40 МБ общей памяти.

От одной из функций общее время выполнения:

128 МБ в холодном состоянии: ОТЧЕТ Продолжительность: 21775,92 мс Оплачиваемая продолжительность: 21800 мс Размер памяти: 128 МБ Макс. используемая память: 35 МБ

128 МБ в горячем состоянии: ОТЧЕТ Продолжительность: 1326,76 мс Оплачиваемая продолжительность: 1400 мс Размер памяти: 128 МБ Макс. используемая память: 37 МБ

256 МБ в холодном состоянии: ОТЧЕТ Продолжительность: 11159,49 мс Оплачиваемая продолжительность: 11200 мс Размер памяти: 256 МБ Макс. используемая память: 39 МБ

256 МБ в горячем состоянии: ОТЧЕТ Продолжительность: 792,37 мс Оплачиваемая продолжительность: 800 мс Объем памяти: 256 МБ Макс. используемый объем памяти: 39 МБ

384 МБ в холодном состоянии: ОТЧЕТ Продолжительность: 7566,07 мс Оплачиваемая продолжительность: 7600 мс Размер памяти: 384 МБ Макс. используемая память: 43 МБ

384 МБ в горячем состоянии: ОТЧЕТ Продолжительность: 850,59 мс Оплачиваемая продолжительность: 900 мс Размер памяти: 384 МБ Макс. используемая память: 47 МБ

просто для смеха:

1024 МБ в холодном состоянии: ОТЧЕТ Продолжительность: 3309,12 мс Оплачиваемая продолжительность: 3400 мс Размер памяти: 1024 МБ Макс. используемая память: 38 МБ

1024 МБ в горячем состоянии: ОТЧЕТ Продолжительность: 677,57 мс Оплачиваемая продолжительность: 700 мс Размер памяти: 1024 МБ Макс. используемая память: 41 МБ

Это много накладных расходов для холодного запуска.

Для сравнения, вот функция nodejs, которая выполняет примерно половину работы (более старая версия до переноса на C#), но тот же тип работы (взятие SNS, запись чего-то в базу данных, сохранение чего-то в S3), но это кажется верным для всей плата с другими функциями у нас есть:

128 МБ Холодный: ОТЧЕТ Продолжительность: 262,58 мс Оплачиваемая продолжительность: 300 мс Размер памяти: 128 МБ Макс. используемая память: 19 МБ

128 МБ Горячий: ОТЧЕТ Продолжительность: 134,79 мс Оплачиваемая продолжительность: 200 мс Размер памяти: 128 МБ Макс. используемая память: 19 МБ

Процент накладных расходов в холодную погоду кажется гораздо более разумным.

Я использую инструменты Visual Studio AWS для загрузки пакета — код предварительно скомпилирован для целевой платформы перед загрузкой, верно? Я что-то упускаю или это нормально? Другие числа, указанные здесь, меньше, но я не знаю распределения памяти.

Время холодной загрузки является проблемой при создании Slack-ботов, так как Slack отключается через 3000 мс. Очень хотелось бы, чтобы был способ гарантировать, что экземпляр всегда доступен.

Я открыл тикет в техподдержку по поводу этой проблемы. Если я узнаю что-нибудь полезное, я поделюсь этим здесь.

в то время как есть много обходных путей, чтобы поддерживать лямбду в тепле с помощью пингов cloudwatch и т. д., в конечном итоге время холодного запуска должно быть удобным для вас. Вы можете оптимизировать холодные пуски, но не можете их избежать. Почти уверен, что когда произойдет автоматическое масштабирование, новые лямбда-выражения также будут масштабироваться из холода.

@bjorg, чтобы гарантировать, что экземпляры всегда доступны, возможно, лучше рассмотреть EC2 или ECS.

@InsidiousForce Я удивлен, что у вас 21- создадите тикет в @SpoonOfDoom.

@yunspace ересь! :)

C# Lambda All Things!

Итак, после долгих разговоров с дружелюбным персоналом службы технической поддержки Amazon основной вывод из разговора таков:
Вы можете попытаться оптимизировать свой код - уменьшить размер файла, выкидывать библиотеки, которые не являются абсолютно необходимыми, постарайтесь иметь как можно меньше статики и другие вещи, которые инициализируются при запуске, как это возможно, и увеличения курса выделяется память для увеличения мощности процессора, как обсуждалось в этой теме. Поддержание работоспособности Lambda путем регулярных вызовов может растянуть проблему, но не устранить ее. Интервал в 4 минуты кажется лучшим значением для большинства случаев, но очевидно, что основное поведение не является полностью детерминированным, поэтому это ненадежное правило. И даже тогда, он не полностью устранить эту проблему.

Суть, к сожалению, в том, что вы можете добиться чего-то, только делая все это, и в какой-то момент выделение большего количества памяти становится невозможным. Вы всегда будете иметь эти времена начали холодные, и в то время как вы можете быть в состоянии уменьшить их, вы, вероятно, не будете в состоянии уменьшить их до точки, где это разумно для публики лица API или что-то подобное - кажется, что если вы не может позволить себе просто ждать, и теперь каждый раз, то C # Lambda не для вас, и вы лучше с экземпляром EC2 или, может быть (как мы делаем сейчас) Elastic Beanstalk, если вы хотите, простое развертывание и автоматическое масштабирование ,
Мы теперь превратить наши лямбды в проект Web API ASP.NET, что позволяет нам сделать еще комфортное размещение от Visual Studio и сохранить некоторые параметры автоматического масштабирования.

TL;DR: не похоже, что есть надежный способ обойти эту проблему. Использование EBS или EC2 вместо этого.

Закрытие из-за отсутствия активности. Также этот репозиторий в основном предназначен для поддержки клиентских библиотек и инструментов. Лучшее место для обсуждения — форумы Lambda, за которыми следит команда обслуживания Lambda.

Всем привет!
Я написал статью, в которой сравниваю Python, PHP, Java, Ruby и C#.
Можете ли вы проверить это и сказать свое мнение о нем? (Это не чисто технический материал, а более обобщающий для начинающих)
https://www.cleveroad.com/blog/python-vs-other-programming-languages

Мне эта статья не помогла.

Во-первых, это было не сравнение. Заголовок на странице гласит: «ПРЕИМУЩЕСТВА ИСПОЛЬЗОВАНИЯ PYTHON ПЕРЕД ДРУГИМИ ЯЗЫКАМИ», поэтому это явно НЕ сравнение.

Во-вторых, НЕТ ЯЗЫКА, СООТВЕТСТВУЮЩЕГО ВСЕМ ТРЕБОВАНИЯМ!

Например, создание сложных фреймворков с помощью языка сценариев невероятно сложно. Ваше замечание о Python: «Мы можем сказать, что Python — это минималистичный язык. Его очень легко писать и читать. И когда приходит время подумать о проблеме, разработчик может сосредоточиться на проблеме, а не на языке и его синтаксис». даже не начинает помогать с богатыми моделями и взаимодействиями между компонентами модели.

Хотя мы, похоже, пришли к мысли, что микросервисы ответят на все вопросы, я был в этой игре достаточно долго, чтобы понять, что это очень наивный подход.

Проблемы приходят во МНОГИХ формах.

Я согласен с genifycom. В дополнение к этому, есть некоторые моменты, которые кажутся сомнительными, если не ошибочными. Например, заявление о том, что вы не можете создавать сетевые приложения (я полагаю, это означает распределенные вычисления?) в Python, кажется неосведомленным , а заявление о том, что в C# не так много доступных библиотек, является странным заявлением, учитывая, что доступно примерно 100 тыс. пакетов. только на Nuget .
Кроме того, у Python нет «одного способа решить проблему» — всегда есть несколько способов решения проблем, и это обычно вообще не имеет ничего общего с языком.
Затем есть один момент, в котором вы, кажется, противоречите сами себе, когда вы говорите в своей диаграмме, что Python не может создавать кроссплатформенные приложения (да? Это кажется неправильным), а затем в тексте «Python совместим почти со всеми современными операционными системами» .
Есть и другие более мелкие проблемы — например, теоретически вы можете кодировать на C# с помощью Notepad и компилировать через командную строку, IDE не требуется, в то время как правильная IDE, такая как IntelliJ, также значительно упрощает разработку Python.

Вдобавок ко всему этому, я не уверен, что проблема GitHub с почти год бездействия — это правильный способ рекламы вашего блога.

genifycom и SpoonOfDoom Спасибо за ваше мнение, я приму его к сведению.

Вот еще одно мнение, более благоприятное для .Net Core:
https://read.acloud.guru/comparing-aws-lambda-performance-of-node-js-python-java-c-and-go-29c1163c2581

Любые советы о том, как сделать код С# более эффективным с точки зрения .NET для обработчиков лямбда?
Некоторые из примеров вопросов, которые я пытаюсь решить:
1) Повысит ли статическое значение лямбда-функций повторное использование лямбда-контекста и повысит ли производительность?
2) Если я сделаю класс функций (в котором есть все обработчики лямбда) одноэлементным классом, улучшит ли это производительность?
3) Если я создам константы/переменные только для чтения и разделю их между лямбда-функциями, улучшит ли это производительность?

Если у кого-то есть информация, подскажите

@niraj-bpsoftware, почему вы пытаетесь и публикуете здесь свои выводы? Мне было бы очень интересно увидеть, есть ли заметная разница. Честно говоря, я бы очень удивился, если бы что-то из этого оказало влияние.

1) Преимущество отказа от создания экземпляра, которое представляет собой единовременную фиксированную стоимость в течение всего срока службы функции, кажется абсолютно минимальной и выходит далеко за пределы любого измеримого порога.

2) Я не могу говорить об этом, потому что я этого не делаю. Однако, если вы обработчики - это разные лямбда-функции, то они ничего общего не имеют, поскольку все они работают в отдельных процессах/контейнерах, насколько я понимаю.

3) То же.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги