

A versão 4 (V4) do AWS SDK para .NET foi lançada\!

Para obter informações sobre mudanças significativas e migrar seus aplicativos, consulte o tópico [ de ](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html) migração.

 [![Orange button with text "Click here for details".](https://docs.aws.amazon.com/pt_br/sdk-for-net/v4/developer-guide/images/BannerButton_less-round.png)](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html)

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Práticas recomendadas de desempenho para o AWS SDK para .NET
<a name="net-dg-performance"></a>

A forma como você cria clientes, processa respostas e configura seu aplicativo tem um grande efeito na taxa de transferência, na latência e no uso da memória. Este tópico descreve os padrões de uso e configuração que ajudam seus aplicativos a serem executados de forma eficiente e confiável. Esses padrões são mais importantes sob alta carga ou em ambientes com recursos limitados, como contêineres e funções sem servidor. Seguir essas práticas pode melhorar o desempenho e evitar problemas comuns, como respostas lentas, travamentos e alto uso de memória.

As práticas mais impactantes são as seguintes:
+ [Reutilize um único cliente de serviço de longa duração ](#net-dg-performance-reuse-clients) em vez de criar um por solicitação.
+ [Descarte respostas e fluxos ](#net-dg-performance-dispose) para que as conexões de rede sejam liberadas de volta ao pool de conexões.
+ [Use`async`/`await`corretamente ](#net-dg-performance-async) e nunca bloqueie chamadas assíncronas do SDK.
+ [Configure a coleta de lixo do.NET ](#net-dg-performance-gc) para ambientes restritos, como o AWS Lambda Amazon ECS.
+ [Gerenciar conexões HTTP e limites de conexão](#net-dg-performance-connections)Gerencie conexões HTTP e limites de conexão sob alta taxa de transferência.

Antes de começar, certifique-se de ter [[ configurado seu ambiente ](configuring-the-sdk.md) e seu projeto](net-dg-config.md).

## Reutilize um cliente de serviço único e duradouro
<a name="net-dg-performance-reuse-clients"></a>

Clientes de serviços, como o [AmazonS3Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TS3Client.html), são *seguros para uso em processos*, [AmazonDynamoDBClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TDynamoDBClient.html) são relativamente * caros de construir e duram muito tempo. * * * A construção de um cliente resolve as informações da região e do endpoint e estabelece a infraestrutura HTTP subjacente. Crie um cliente por serviço e reutilize-o durante toda a vida útil do seu aplicativo. Se você ligar para mais de uma região, crie um cliente separado para cada região.

**Atenção**  
Não crie um novo cliente de serviço para cada solicitação ou dentro de um loop. A criação de clientes altera repetidamente a infraestrutura HTTP subjacente, o que adiciona latência mensurável. Ele também pode exaurir soquetes ou alças e fazer com que as solicitações falhem ou fiquem suspensas sob carga.

Em aplicativos que usam injeção de dependência, registre o cliente como um singleton. O método de `AddAWSService` extensão do `AWSSDK.Extensions.NETCore.Setup` NuGet pacote registra o cliente com uma vida útil padrão de`ServiceLifetime.Singleton`. O cliente é criado na primeira vez que é solicitado e a mesma instância é reutilizada durante a vida útil do processo. Para obter mais informações sobre o registro de AWS serviços com injeção de dependência e as opções de leitura da configuração, consulte. [AWSSDK.Extensions.NETCore.Setup e iConfiguration](net-dg-config-netcore.md)

Você também pode registrar um cliente como um singleton manualmente.

```
builder.Services.AddSingleton<IAmazonS3>(_ => new AmazonS3Client());
```

**nota**  
Como `AddAWSService` registra o cliente como um singleton por padrão, não descarte o cliente que ele fornece. Se você precisar de uma vida útil não padrão, passe um `ServiceLifetime` valor diferente para o `lifetime` parâmetro opcional de`AddAWSService`.

Reutilizar o cliente ** não ** significa que você deva parar de descartar respostas por operação. Reutilize o cliente durante a vida útil do aplicativo, mas continue descartando as respostas e os fluxos que as operações individuais retornam, conforme descrito em. [Descarte respostas e fluxos](#net-dg-performance-dispose)

## Descarte respostas e fluxos para liberar conexões
<a name="net-dg-performance-dispose"></a>

Alguns objetos de resposta do SDK transmitem um fluxo de rede ao vivo. O exemplo mais comum é [ GetObjectResponse ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TGetObjectResponse.html) o que implementa `IDisposable` e expõe o conteúdo do objeto por meio de sua `ResponseStream` propriedade. A resposta mantém uma conexão HTTP aberta até que o stream seja totalmente lido ou a resposta seja descartada. Se você vazar essas respostas (por exemplo, chamando `GetObject` um loop sem descartar cada resultado), as conexões abertas se acumularão até que o pool de conexões se esgote e a próxima chamada seja bloqueada. Essa é a causa por trás dos relatos de downloads que “param aleatoriamente” ou param no enésimo objeto.

Sempre inclua uma resposta de streaming em uma `using` declaração e leia ou copie a transmissão imediatamente.

```
using Amazon.S3;
using Amazon.S3.Model;

// s3Client is a reused, long-lived client.
var request = new GetObjectRequest { BucketName = bucketName, Key = key };

using var response = await s3Client.GetObjectAsync(request);
await response.WriteResponseStreamToFileAsync(filePath, append: false, CancellationToken.None);
```

Descartar a resposta e descartá-la `ResponseStream` são equivalentes; qualquer uma delas fecha o fluxo de rede subjacente e retorna a conexão ao pool.

**dica**  
Se você precisar apenas de metadados do objeto, como tamanho, hora da última modificação, tipo de conteúdo ou ETag, ligue para `GetObjectMetadata` ou em vez de. `GetObjectMetadataAsync` `GetObject` A operação de metadados emite uma `HEAD` solicitação HTTP e não transfere o corpo do objeto, portanto, não há fluxo de conteúdo para gerenciar.  

```
var metadata = await s3Client.GetObjectMetadataAsync(bucketName, key);
Console.WriteLine($"Size: {metadata.ContentLength} bytes");
```

**Atenção**  
Tipos de resposta e stream, como `GetObjectResponse` não implementam um finalizador, então você não pode confiar na coleta de lixo para liberar suas conexões para você. Você deve descartar respostas e fluxos de forma determinística com `using` ou com uma chamada explícita. `Dispose`

## Use async/await corretamente
<a name="net-dg-performance-async"></a>

No domínio.NET moderno, as operações de serviço no AWS SDK para .NET são assíncronas e retornam a. `Task` No .NET Framework, também existem métodos síncronos, mas as chamadas assíncronas escalam melhor e são recomendadas. Consuma operações com `await` e propague `async` por todas as camadas do seu código até o ponto de entrada. Para obter mais informações sobre programação assíncrona com o SDK, consulte. [Programação assíncrona](sdk-net-async-api.md)

**Atenção**  
Não bloqueie uma chamada de SDK assíncrona com`.Result`,, ou. `.Wait()` `.GetAwaiter().GetResult()` Esse * padrão de * sincronização sobre assíncrona é uma causa comum de travamento de aplicativos:  
Sob carga, as chamadas de bloqueio consomem threads mais rápido do que o pool de threads pode crescer, portanto, as continuações não podem ser executadas. Essa falta de * pool de threads * aparece como um travamento indefinido e é o modo de falha dominante no.NET moderno (onde não tem padrão). ASP.NET Core `SynchronizationContext`
Alguns contextos capturam um`SynchronizationContext`, como aplicativos clássicosASP.NET,, Windows Forms WPFBlazor WebAssembly, e .NET Framework. Nesses contextos, bloquear o thread de chamada enquanto uma continuação precisa desse mesmo thread produz um * impasse. * As operações no SDK são usadas `ConfigureAwait(false)` internamente, então elas não publicam suas continuações no contexto capturado. O impasse surge de um `async` código em outra parte da sua cadeia de chamadas que o captura. O consumo contínuo de chamadas de `await` SDK evita totalmente o problema.

O método a seguir bloqueia a chamada assíncrona e pode bloquear ou privar o pool de threads.

```
// Anti-pattern: do not do this.
public GetObjectResponse Get(GetObjectRequest request)
{
    return s3Client.GetObjectAsync(request).Result;
}
```

Em vez disso, faça o método `async` e `await` a chamada.

```
public async Task<GetObjectResponse> GetAsync(GetObjectRequest request)
{
    return await s3Client.GetObjectAsync(request);
}
```

Recomendações adicionais para código assíncrono:
+ Passe `CancellationToken` a para cada operação para que uma chamada lenta ou paralisada possa ser cancelada em vez de suspensa. Para obter mais informações, consulte [Usar o parâmetro `CancellationToken` para tempos limite](retries-timeouts.md#timeouts-async).
+ Não engula exceções em um bloco vazio`catch`. Fazer isso oculta a falha real e torna um travamento indistinguível de um erro. Capture exceções específicas e registre-as.
+ Ao relançar uma exceção capturada, use `throw;` em vez de `throw ex;` para que o rastreamento de pilha original seja preservado.
+ Se você precisar chamar de um limite síncrono, trate-o como último recurso e isole o trabalho do contexto capturado em vez de tornar as chamadas de bloqueio o padrão padrão.

## Configurar a coleta de lixo do.NET para AWS Lambda e Amazon ECS
<a name="net-dg-performance-gc"></a>

Quando um contêiner parece ter um “vazamento de memória”, o coletor de lixo do.NET (GC) pode estar retendo a memória recuperada para reutilização. Como resultado, a memória do processo pode parecer alta e estável mesmo quando a pilha gerenciada não está crescendo. Além disso, o GC não detecta automaticamente o limite de memória de um contêiner (seu limite de cgroup). Em um ambiente restrito, a pilha pode então crescer em direção à memória do host, em vez do limite do contêiner. Isso pode levar ao encerramento `OutOfMemoryException` ou ao encerramento do contêiner.

Para ajudar o GC a funcionar bem em ambientes restritos:
+ Defina um limite de memória explícito no contêiner para que o GC honre o limite do cgroup, and/or defina a variável de ambiente `DOTNET_GCHeapHardLimit` (um valor absoluto de byte, em hexadecimal) ou `DOTNET_GCHeapHardLimitPercent` de ambiente para limitar a pilha gerenciada. Em vários casos relatados de falta de memória do Amazon ECS, definir um limite de memória rígida resolveu as falhas.
+ Em hosts pequenos AWS Lambda e no Amazon ECS, considere desativar a coleta de lixo simultânea (em segundo plano) para que o coletor não reserve memória adicional; por exemplo, defina a variável de `DOTNET_gcConcurrent` ambiente como ou `<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>` defina-a no `0` arquivo do projeto.
+ Limite sua concorrência. Iniciar várias operações ao mesmo tempo, como chamar `Task.WhenAll` uma grande coleção, infla a memória do processo e pode prejudicar o pool de conexões. Em vez disso, limite o grau de paralelismo. Por exemplo, evite esse padrão ilimitado:

  ```
  // Anti-pattern: starts one task per item with no limit.
  await Task.WhenAll(keys.Select(key => s3Client.GetObjectMetadataAsync(bucket, key)));
  ```

  Em vez disso, limite a simultaneidade com`Parallel.ForEachAsync`:

  ```
  var options = new ParallelOptions { MaxDegreeOfParallelism = 10 };
  await Parallel.ForEachAsync(keys, options, async (key, token) =>
  {
      await s3Client.GetObjectMetadataAsync(bucket, key, token);
  });
  ```

Para obter mais informações sobre essas configurações, consulte Opções de configuração [ de tempo de execução para coleta de lixo ](https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector) em learn.microsoft.com. Para obter orientações específicas sobre AWS computação, consulte a postagem do blog AWS Developer Tools [ Configurando a coleta de lixo do.NET para Amazon ECS e. AWS Lambda](https://aws.amazon.com/blogs/developer/configuring-net-garbage-collection-for-amazon-ecs-and-aws-lambda)

## Gerenciar conexões HTTP e limites de conexão
<a name="net-dg-performance-connections"></a>

Em alta taxa de transferência, dois problemas relacionados à conexão são comuns. A primeira é abrir muitas conexões de curta duração. Isso esgota as portas efêmeras, deixa os soquetes dentro e adiciona latência de handshake `TIME_WAIT` TCP e TLS. A segunda é ter poucas conexões disponíveis, o que prejudica o paralelismo. A reutilização de um cliente único e duradouro (consulte[Reutilize clientes de serviços](#net-dg-performance-reuse-clients)) é a base para um pool de conexões saudável, porque o agrupamento depende da reutilização do cliente.

Para ajustar o número de conexões simultâneas por endpoint, defina a `MaxConnectionsPerServer` propriedade na configuração do cliente. Quando essa propriedade é `null` (o padrão), o `HttpClientHandler` padrão subjacente se aplica, o que é efetivamente ilimitado no.NET moderno. Aumente-o somente quando muitas solicitações simultâneas para o mesmo endpoint estiverem bloqueadas nas conexões. Um bom ponto de partida é o número máximo de solicitações simultâneas que você espera por endpoint. Defini-la muito acima das necessidades de sua carga de trabalho desperdiça soquetes sem melhorar a produtividade.

```
using Amazon.S3;

var config = new AmazonS3Config
{
    MaxConnectionsPerServer = 50
};

var s3Client = new AmazonS3Client(config);
```

Se você já usa injeção de dependência, configure seus clientes por meio `AWSSDK.Extensions.NETCore.Setup` de. Essa é a abordagem recomendada quando você usa DI ou registra vários clientes de serviço. Ele centraliza a configuração e facilita a injeção e o teste dos clientes. Você pode definir valores de configuração a partir da configuração do seu aplicativo em vez de no código. Para obter mais informações, consulte [AWSSDK.Extensions.NETCore.Setup e iConfiguration](net-dg-config-netcore.md).

Finalmente, limite seu próprio paralelismo para que você não inicie mais operações simultâneas do que seu limite de conexão permite. Por exemplo, chamadas de portão com um `SemaphoreSlim` tamanho igual ao seu limite de conexão:

```
var throttle = new SemaphoreSlim(50); // match MaxConnectionsPerServer
await throttle.WaitAsync(token);
try
{
    await s3Client.GetObjectAsync(request, token);
}
finally
{
    throttle.Release();
}
```

## Configurar tempos limite e novas tentativas
<a name="net-dg-performance-timeouts"></a>

Os tempos limite e as novas tentativas têm um efeito direto no desempenho percebido. Um `Timeout` valor muito alto permite que uma solicitação paralisada seja bloqueada por muito tempo. Quando um serviço já está retornando erros de limitação, uma política agressiva de repetição adiciona mais solicitações e pode piorar a limitação. Escolha uma política de repetição que atenda à tolerância de latência versus falha do seu aplicativo e permita que exceções genuínas se propaguem em vez de tentar novamente de uma forma que mascare um travamento.

**nota**  
A `Timeout` propriedade não afeta as chamadas assíncronas. Se você estiver usando chamadas assíncronas, consulte em vez disso. [Usar o parâmetro `CancellationToken` para tempos limite](retries-timeouts.md#timeouts-async)

Para obter mais informações sobre os modos de repetição e a `Timeout` propriedade (`ReadWriteTimeout`aplicável somente ao.NET Framework), além de exemplos de como configurá-los, consulte[Novas tentativas e tempos limite](retries-timeouts.md). `MaxErrorRetry`

## Otimize o streaming e as transferências de objetos grandes (Amazon S3)
<a name="net-dg-performance-streaming"></a>

Para carregar e baixar objetos grandes, ou muitos objetos, use a [ TransferUtility ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TTransferUtility.html) classe no `Amazon.S3.Transfer` namespace. Ele carrega e baixa em paralelo usando transferências de várias partes e gerencia fluxos, partes e conexões para você. Isso é mais rápido do que uma transferência de fluxo único e é a maneira recomendada de mover objetos grandes.
+ **Download paralelo de várias partes. ** As versões anteriores do SDK baixavam um objeto como um único stream, em vez de baixar partes em paralelo. A partir da `AWSSDK.S3` versão 4.0.17, `TransferUtility` fornece download de várias partes (paralelo) por meio dos métodos `DownloadWithResponseAsync``OpenStreamWithResponseAsync`, e. `DownloadDirectoryWithResponseAsync` Quando você usa`OpenStreamWithResponseAsync`, as partes do objeto são armazenadas em buffer na memória enquanto você consome o fluxo retornado. Controle quantas peças são armazenadas em buffer com a `MaxInMemoryParts` propriedade de [ TransferUtilityOpenStreamRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TTransferUtilityOpenStreamRequest.html). Para a maioria das transferências, prefira`TransferUtility`. Baixe você mesmo os intervalos de bytes com a `ByteRange` propriedade de [ GetObjectRequest ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TGetObjectRequest.html) somente quando precisar de um intervalo específico ou de um esquema de paralelismo personalizado. Para obter mais informações, consulte [ Introdução ao suporte de download de várias partes para o AWS SDK para .NET Transfer Manager ](https://aws.amazon.com/blogs/developer/introducing-multipart-download-support-for-aws-sdk-for-net-transfer-manager/) no blog de ferramentas para AWS desenvolvedores.
+ **Tamanho do conteúdo para uploads. ** Um Amazon S3 `PUT` exige um tamanho de conteúdo conhecido e, por padrão, o SDK calcula uma soma de verificação sobre o corpo da solicitação. Quando o comprimento é conhecido e o fluxo é pesquisável, o SDK pode fazer isso sem armazenar o objeto inteiro na memória. Ele `TransferUtility` lida com fluxos não pesquisáveis para você, armazenando em buffer conforme necessário. Se, em vez disso, você ligar `PutObjectAsync` diretamente com um fluxo não pesquisável (como um corpo de solicitação brutoASP.NET Core), a solicitação poderá falhar. Forneça um stream pesquisável, defina o tamanho do conteúdo explicitamente ou configure como o SDK calcula as somas de verificação. Para obter mais informações, consulte Proteções [ de integridade de dados ](https://docs.aws.amazon.com/sdkref/latest/guide/feature-dataintegrity.html) no Guia de referência de AWS SDKs e ferramentas.
+ **Dimensionamento da peça. ** O Amazon S3 permite um máximo de 10.000 peças por upload de várias partes. Quando o tamanho total é conhecido, o SDK calcula automaticamente um tamanho de peça que permanece dentro desse limite. Você precisa `PartSize` se configurar principalmente para streams cuja duração não é conhecida com antecedência. Caso contrário, pequenas partes padrão podem exceder o limite de um upload muito grande. Um tamanho de peça maior também reduz a sobrecarga por peça, ao custo de mais memória por peça.

## Diagnosticar problemas de desempenho
<a name="net-dg-performance-diagnose"></a>

Quando você investiga uma lentidão, um travamento ou um aparente vazamento, os seguintes sinais ajudam você a encontrar a causa rapidamente:
+ Um número crescente de soquetes no `TIME_WAIT` estado `CLOSE_WAIT` or (visível com`netstat`) é a impressão digital de respostas não descartadas ou de clientes sendo criados e descartados por solicitação. Consulte [Descarte respostas e fluxos](#net-dg-performance-dispose) e [Reutilize clientes de serviços](#net-dg-performance-reuse-clients).
+ Ative as métricas de solicitação e o registro de respostas para confirmar se as solicitações estão realmente sendo enviadas e para medir a latência. Defina as propriedades do [ LoggingConfig ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Util/TLoggingConfig.html) objeto em [ AWSConfigs ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Amazon/TAWSConfigs.html) antes de criar seus clientes de serviço. Um cliente captura configurações, como `LogMetrics` quando ele é construído.

  ```
  using Amazon;
  
  AWSConfigs.LoggingConfig.LogMetrics = true;
  AWSConfigs.LoggingConfig.LogResponses = ResponseLoggingOption.OnError;
  ```
+ Ao investigar a memória, diferencie a memória de todo o processo da pilha gerenciada. A memória de processo alta, mas estável, geralmente é o GC que contém a memória recuperada em vez de um vazamento. Consulte [Configurar a coleta de lixo](#net-dg-performance-gc).