Первый. Спасибо за перенос 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
Могу ли я что-нибудь сделать, чтобы оптимизировать время вызова на моей стороне? Это то, над чем вы все еще работаете? Просто интересно состояние. Спасибо!
Производительность — это то, над чем мы всегда будем продолжать работать с Lambda и всеми поддерживаемыми средами выполнения. У каждого языка есть свои сильные и слабые стороны, поэтому у нас такие веселые языковые войны :)
Этот тест просто измеряет время запуска среды выполнения языка, что является чем-то вроде того, что динамические языки, такие как Node.js и Python, всегда были быстрее по сравнению со статическими языками, такими как C# и Java, из-за отсутствия проверки типов и более ленивой загрузки зависимостей.
Извините, я не хотел закрывать его. Смело продолжайте разговор.
Спасибо, что держите это открытым. Это не критика, а основа для открытой дискуссии.
В своем ответе вы упомянули, что тест измеряет время запуска языка. Я хотел бы внести больше ясности в это утверждение. Я думал, что при первом обращении приложение инициализируется (при необходимости), а затем запускается, но при последующих обращениях оно разогревается. Если он запускается каждый раз, то нет смысла перемещать однократный код (например, чтение значений конфигурации) в конструктор класса обработчика, поскольку он все равно создается при каждом вызове. Я не так понял из вашей презентации re:Invent. Не могли бы вы уточнить. Спасибо!
Просто чтобы подтвердить свое понимание, я перечитал, как работает контейнер Lambda здесь: http://docs.aws.amazon.com/lambda/latest/dg/lambda-introduction.html.
@bjorg @normj документация в этом отношении довольно расплывчата :(
Я предоставил ниже отзыв и надеюсь, что он будет разъяснен
@bjorg то, что вы здесь разместили, не является _холодным временем запуска Lambda_. Но _теплое время отклика_.
Когда функция C# впервые запускается с нуля, это может занять до нескольких сотен миллисекунд (в моем случае это 500 мс). После того, как он прогреется, он останется в живых и будет обслуживать запросы с большей скоростью, аналогичной той, которую вы опубликовали (в моем случае это было от 0,9 до 1 мс). В конце концов, он умрет в конце своего жизненного цикла, или произойдет автомасштабирование, и запустится больше холодных лямбда-выражений. Чтобы узнать время запуска, подождите 15 минут или около того, затем нажмите «Тест».
Так что да, вы все еще помещаете вещи в конструкторы. Потому что вы не получаете совершенно новую лямбду каждый раз, когда нажимаете «Тест». Но вы получите совершенно новую лямбду, если будете щелкать только раз в час.
С точки зрения оптимизации, для _времени холодного запуска_ вы можете:
Оптимизация _теплого времени отклика_ действительно не имеет особого смысла:
helloworld
или toUpper
.Также не путайте производительность со временем отклика. Тот факт, что 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 ересь! :)
Итак, после долгих разговоров с дружелюбным персоналом службы технической поддержки 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) То же.
Самый полезный комментарий
@yunspace ересь! :)