Recentemente, temos experimentado um aumento no uso crescente da memória de certas funções, resultando em Process exited before completing request
e uma nova instância lambda.
Notamos isso pela primeira vez em 11/09/2018 às 12:43:06. Pouco antes disso, fizemos uma implantação alterando o tempo de execução de dotnetcore2.0 para 2.1. Nenhuma outra alteração significativa foi feita no código que pudesse causar um vazamento de memória e ele estava sendo executado sem erros antes da implantação.
Reproduzi o erro com o seguinte código:
public class DynamoDBTrigger
{
private IAmazonDynamoDB _ddbClient;
public DynamoDBTrigger()
{
_ddbClient = new AmazonDynamoDBClient();
}
[LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
public void Process(DynamoDBEvent ev, ILambdaContext context)
{
foreach (var record in ev.Records)
{
var item = Convert(record.Dynamodb.NewImage);
context.Logger.Log(JsonConvert.SerializeObject(item));
}
}
private Item Convert(Dictionary<string, AttributeValue> attributeMap)
{
using (var context = new DynamoDBContext(_ddbClient))
{
var doc = Document.FromAttributeMap(attributeMap);
return context.FromDocument<Item>(doc, new DynamoDBOperationConfig { OverrideTableName = Environment.GetEnvironmentVariable("Table") });
}
}
}
Estou escrevendo uma linha por segundo na tabela de acionamento e vejo um aumento de memória de cerca de 1 MB a cada 3 chamadas, levando a 128 MB por um tempo antes de registrar isso:
START RequestId: 3e5acba1-36fd-4a3a-bf84-659c5488437b Version: $LATEST
END RequestId: 3e5acba1-36fd-4a3a-bf84-659c5488437b
REPORT RequestId: 3e5acba1-36fd-4a3a-bf84-659c5488437b Duration: 2293.32 ms Billed Duration: 2300 ms Memory Size: 128 MB Max Memory Used: 128 MB
RequestId: 3e5acba1-36fd-4a3a-bf84-659c5488437b Process exited before completing request
Eu tentei e a mesma coisa acontece com uma configuração de 256 MB e o aumento parece linear.
Observei algo semelhante com um proxy API Gateway Lambda que usa ApiGatewayProxyFunction
entrypoint. Nesse caso, a memória aumenta linearmente até atingir o limite em que permanece por um tempo antes que o ASP.NET pareça querer limpar alguma memória:
Destacando três observações:
1) alta duração na invocação antes e depois da coleta de lixo
2) A memória máxima usada caiu de 128 MB para 68 MB
3) Mesmo fluxo de log usado, então a instância lambda não é descartada
Sinto que não mudamos nada nem trouxemos novos pacotes. É possível que o lançamento do .NET Core 2.1.4 na mesma época da semana passada tenha causado essa mudança de comportamento?
Também notei um padrão repetível. Quando eu executo uma publicação em um lambda C # e, em seguida, executo-o e vejo seu consumo de memória, ele tem um valor, digamos 74 MB. Quando eu simplesmente o republicar novamente, sem alterações, sem recompilação, ele será executado com um consumo de memória menor, digamos 66 MB
Também estou vendo projetos que estavam bem, agora excedendo o limite de 128 MB e o processo sendo encerrado prematuramente.
128 MB mal consegue iniciar o processo, muito menos executá-lo de forma eficaz. Tendo testado recentemente o desempenho de inicialização a frio para uma implementação relativamente simples do ASP.NET Core Lambda Proxy, usando todos os limites de memória disponíveis, posso dizer com segurança que os comentadores antes de mim estão destruindo o GC em todo o ciclo de vida da solicitação e causando seus próprios problemas de memória.
Eles observarão partidas a frio de segundos de um dígito baixas e tempos de resposta abaixo de milissegundos se aumentarem seu limite de memória a um nível adequado para as necessidades de memória de seu aplicativo, que minimiza os tempos de inicialização e execução sem aumentar os custos por iniciar / executar.
Eu tenho um lambda com 3 GB de memória. Mas também vejo o mesmo problema. No início, meu processo leva cerca de 1,5G, mas continua aumentando gradualmente. Às vezes, a mesma entrada consome quantidades totalmente diferentes de memória (levando a encerramentos). Não há nada aleatório em meu código que faça com que o consumo de memória varie.
@twopointzero 128mb era suficiente para o lambda em meu exemplo antes de atualizá-lo para .NET core 2.0.
Concordo que 128 MB não é suficiente para ASP.NET Lambda Proxies, mas isso não faz uso de Microsoft.AspNetCore.App
Isso tem a ver com o fato de o recipiente estar quente mesmo após a conclusão da função. Em vez de retornar "", nil. entraria em pânico e resolveria o problema. Eu sei que é um hack, mas é assim que funciona.
Alguém ainda está tendo esse problema nas versões atuais do lambda?
Este problema não obteve resposta em 2 semanas. Se você quiser manter esse problema aberto, deixe um comentário abaixo e o fechamento automático será cancelado.
Comentários muito úteis
Também notei um padrão repetível. Quando eu executo uma publicação em um lambda C # e, em seguida, executo-o e vejo seu consumo de memória, ele tem um valor, digamos 74 MB. Quando eu simplesmente o republicar novamente, sem alterações, sem recompilação, ele será executado com um consumo de memória menor, digamos 66 MB
Também estou vendo projetos que estavam bem, agora excedendo o limite de 128 MB e o processo sendo encerrado prematuramente.