Réglage du niveau de performance pour les chargements et les téléchargements avec .NET

Lorsqu’une application transfère des données à l’aide de la bibliothèque cliente Stockage Azure pour .NET, plusieurs facteurs peuvent affecter la vitesse, l’utilisation de la mémoire et même la réussite ou l’échec de la demande. Pour optimiser les performances et la fiabilité des transferts de données, il est important de configurer les options de transfert d’une bibliothèque de client de manière proactive en fonction de l’environnement dans lequel l’application s’exécute.

Cet article décrit plusieurs considérations relatives au réglage des options de transfert de données, et les conseils s’appliquent à toute API qui accepte StorageTransferOptions en tant que paramètre. Lorsqu’elle est correctement paramétrée, la bibliothèque cliente peut distribuer efficacement les données entre plusieurs requêtes, ce qui peut améliorer la vitesse d’opération, l’utilisation de la mémoire et la stabilité du réseau.

Optimisation des performances avec StorageTransferOptions

Le réglage correct des valeurs dans StorageTransferOptions est essentiel pour des performances fiables pour les opérations de transfert de données. Les transferts de stockage sont divisés en plusieurs sous-transferts en fonction des valeurs des propriétés définies dans une instance de ce struct. La taille maximale de transfert prise en charge varie selon l’opération et la version du service. Veillez donc à consulter la documentation pour déterminer les limites. Pour plus d’informations sur les limites de taille de transfert pour le stockage Blob, consultez Cibles de mise à l’échelle pour le stockage Blob.

Les propriétés suivantes de StorageTransferOptions peuvent être paramétrées en fonction des besoins de votre application :

Notes

Bien que le structStorageTransferOptions contienne des valeurs nullables, les bibliothèques clientes utilisent les valeurs par défaut pour chaque valeur individuelle, si elles ne sont pas fournies. Ces valeurs par défaut sont généralement performantes dans un environnement de centre de données, mais elles ne sont pas susceptibles d’être adaptées aux environnements de consommation domestique. Un réglage médiocre de StorageTransferOptions peut entraîner des opérations excessivement longues et même des délais d’attente de demande. Il est préférable d’être proactif dans le test des valeurs dans StorageTransferOptions, et de les paramétrer en fonction des besoins de votre application et de votre environnement.

InitialTransferSize

InitialTransferSize est la taille de la première requête de plage en octets. Une requête de plage HTTP est une requête partielle, dont la taille est définie par InitialTransferSize dans ce cas. Les blobs inférieurs à cette taille sont transférés dans une seule requête. Les blobs supérieurs à cette taille continuent d’être transférés en blocs de taille MaximumTransferSize.

Il est important de noter que la valeur pour laquelle vous spécifiez MaximumTransferSizene limite pas la valeur que vous définissez pour InitialTransferSize. InitialTransferSize définit une limitation de taille distincte pour une demande initiale permettant d’effectuer l’ensemble de l’opération en même temps, sans sous-transfert. Il arrive souvent que vous souhaitiez que InitialTransferSize soit au moins aussi importante que la valeur que vous définissez pour MaximumTransferSize, si ce n’est plus. En fonction de la taille du transfert de données, cette approche peut être plus performante, car le transfert est effectué avec une seule demande et évite la surcharge de plusieurs demandes.

Si vous n’êtes pas sûr de la valeur la mieux adaptée à votre situation, une option sécurisée consiste à définir InitialTransferSize sur la même valeur que celle utilisée pour MaximumTransferSize.

Notes

Lors de l’utilisation d’un objetBlobClient, le chargement d’un objet blob plus petit que le InitialTransferSizesera à l’aide de Put Blob, plutôt que de Put Block.

MaximumConcurrency

MaximumConcurrency est le nombre maximal de workers qui peuvent être utilisés dans un transfert parallèle. Actuellement, seules les opérations asynchrones peuvent paralléliser les transferts. Les opérations synchrones ignorent cette valeur et fonctionnent en séquence.

L’efficacité de cette valeur est soumise aux limites du pool de connexions dans .NET, ce qui peut restreindre les performances par défaut dans certains scénarios. Pour en savoir plus sur les limites du pool de connexions dans .NET, consultez Limites du pool de connexions .NET Framework et le nouveau Kit de développement logiciel (SDK) Azure pour .NET.

MaximumTransferSize

MaximumTransferSize est la longueur maximale d’un transfert en octets. Comme mentionné précédemment, cette valeur ne limite InitialTransferSizepas, qui peut être supérieure à MaximumTransferSize.

Pour que les données se déplacent efficacement, les bibliothèques clientes peuvent ne pas toujours atteindre la valeur MaximumTransferSize pour chaque transfert. Selon l’opération, la valeur maximale prise en charge pour la taille de transfert peut varier. Par exemple, les objets blob de blocs appelant l’opération Put Block avec une version de service 2019-12-12 ou ultérieure ont une taille de bloc maximale de 4 000 Mio. Pour plus d’informations sur les limites de taille de transfert pour le stockage Blob, consultez le graphique dans Cibles de mise à l’échelle pour le stockage Blob.

Exemple de code

La bibliothèque cliente inclut des surcharges pour les méthodes Uploadet UploadAsync, qui acceptent une instance StorageTransferOptions dans le cadre d’un paramètre BlobUploadOptions . Des surcharges similaires existent également pour les méthodes DownloadToetDownloadToAsync, à l’aide d’un paramètre BlobDownloadToOptions.

L’exemple de code suivant montre comment définir des valeurs pour une instance StorageTransferOptionset passer ces options de configuration en tant que paramètre à UploadAsync. Les valeurs fournies dans cet exemple ne sont pas destinées à être une recommandation. Pour régler correctement ces valeurs, vous devez tenir compte des besoins spécifiques de votre application.

// Specify the StorageTransferOptions
BlobUploadOptions options = new BlobUploadOptions
{
    TransferOptions = new StorageTransferOptions
    {
        // Set the maximum number of parallel transfer workers
        MaximumConcurrency = 2,

        // Set the initial transfer length to 8 MiB
        InitialTransferSize = 8 * 1024 * 1024,

        // Set the maximum length of a transfer to 4 MiB
        MaximumTransferSize = 4 * 1024 * 1024
    }
};

// Upload data from a stream
await blobClient.UploadAsync(stream, options);

Dans cet exemple, nous définissons le nombre de workers de transfert parallèle sur 2, à l’aide de la propriété MaximumConcurrency. Cette configuration ouvre jusqu’à deux connexions simultanément, ce qui permet au chargement de se produire en parallèle. La requête de plage HTTP initiale tente de charger jusqu’à 8 Mio de données, comme défini par la propriété InitialTransferSize. Notez que InitialTransferSize s’applique uniquement aux chargements lors de l’utilisation d’un flux recherché. Si la taille de l’objet blob est inférieure à 8 Mio, une seule requête est nécessaire pour terminer l’opération. Si la taille du blob est supérieure à 8 Mio, toutes les requêtes de transfert suivantes ont une taille maximale de 4 Mio, que nous définissons avec la propriété MaximumTransferSize.

Considérations relatives aux performances pour les chargements

Pendant un chargement, les bibliothèques clientes de stockage divisent un flux de chargement donné en plusieurs sous-chargements en fonction des valeurs définies dans l’instance StorageTransferOptions. Chaque sous-chargement a son propre appel dédié à l’opération REST. Pour un objet BlobClientou un objetBlockBlobClient, cette opération est Put Block. Pour un objetDataLakeFileClient, cette opération est Ajouter des données. La bibliothèque cliente de stockage gère ces opérations REST en parallèle (en fonction des options de transfert) pour terminer le chargement complet.

Selon que le flux de chargement est identifiable ou non, la bibliothèque cliente gère différemment la mise en mémoire tampon et InitialTransferSize, comme décrit dans les sections suivantes. Un flux pouvant être recherché est un flux qui prend en charge l’interrogation et la modification de la position actuelle dans un flux. Pour en savoir plus sur les flux dans .NET, consultez la référence de la classe Stream .

Notes

Les objets blob de blocs ont un nombre maximal de blocs de 50 000 blocs. La taille maximale de votre objet blob de blocs est alors de 50 000 fois MaximumTransferSize.

Mise en mémoire tampon pendant les chargements

La couche REST de stockage ne prend pas en charge la prise en charge d’une opération de chargement REST là où vous l’avez laissée ; les transferts individuels sont terminés ou perdus. Pour garantir la résilience pour les chargements de flux non recherchés, les données de mémoire tampon du client de stockage pour chaque appel REST individuel avant de commencer le chargement. En plus des limitations de vitesse réseau, ce comportement de mise en mémoire tampon est une raison d’envisager une valeur plus petite pour MaximumTransferSize, même lors du chargement dans l’ordre. La diminution de la valeur de MaximumTransferSize réduit la quantité maximale de données mises en mémoire tampon sur chaque requête et chaque nouvelle tentative d’une requête ayant échoué. Si les délais d’expiration pendant les transferts de données d’une certaine taille sont fréquents, la réduction de la valeur MaximumTransferSize réduit le temps de mise en mémoire tampon et peut entraîner de meilleures performances.

Un autre scénario où la mise en mémoire tampon se produit est lorsque vous chargez des données avec des appels REST parallèles pour optimiser le débit réseau. Les bibliothèques clientes ont besoin de sources à partir desquelles elles peuvent lire en parallèle, et étant donné que les flux sont séquentiels, les bibliothèques clientes de stockage mettent en mémoire tampon les données de chaque appel REST individuel avant de commencer le chargement. Ce comportement de mise en mémoire tampon se produit même si le flux fourni est recherché.

Pour éviter la mise en mémoire tampon pendant un appel de chargement asynchrone, vous devez fournir un flux pouvant être recherché et défini MaximumConcurrencysur 1. Bien que cette stratégie fonctionne dans la plupart des situations, il est toujours possible que la mise en mémoire tampon se produise si votre code utilise d’autres fonctionnalités de bibliothèque cliente qui nécessitent une mise en mémoire tampon.

InitialTransferSize lors du chargement

Lorsqu’un flux identifiable est fourni pour le chargement, la longueur du flux est vérifiée par rapport à la valeur de InitialTransferSize. Si la longueur du flux est inférieure à cette valeur, le flux complet est chargé en tant qu’appel REST unique, quelles que soient les autres valeurs de StorageTransferOptions. Dans le cas contraire, le chargement est exécuté en plusieurs parties, comme décrit précédemment. InitialTransferSize n’a aucun effet sur un flux non identifiable et est ignoré.

Considérations relatives aux performances pour les téléchargements

Pendant un téléchargement, les bibliothèques clientes de stockage divisent une requête de téléchargement donnée en plusieurs sous-téléchargements en fonction des valeurs définies dans l’instance StorageTransferOptions. Chaque sous-téléchargement a son propre appel dédié à l’opération REST. Selon les options de transfert, les bibliothèques clientes gèrent ces opérations REST en parallèle pour terminer le téléchargement complet.

Mise en mémoire tampon pendant les téléchargements

La réception de plusieurs réponses HTTP simultanément avec le contenu du corps a des implications pour l’utilisation de la mémoire. Toutefois, les bibliothèques clientes de stockage n’ajoutent pas explicitement d’étape de mémoire tampon pour le contenu téléchargé. Les réponses entrantes sont traitées dans l’ordre. Les bibliothèques clientes configurent une mémoire tampon de 16 kilooctets pour copier des flux d’un flux de réponse HTTP vers un flux de destination ou un chemin de fichier fourni par l’appelant.

InitialTransferSize lors du téléchargement

Pendant un téléchargement, les bibliothèques clientes de stockage effectuent une requête de plage de téléchargement à l’aide de InitialTransferSize avant d’effectuer toute autre chose. Lors de cette requête de téléchargement initiale, les bibliothèques clientes connaissent la taille totale de la ressource. Si la demande initiale a correctement téléchargé tout le contenu, l’opération est terminée. Sinon, les bibliothèques clientes continuent d’effectuer des requêtes de plage jusqu’à MaximumTransferSize jusqu’à ce que le téléchargement complet soit terminé.

Étapes suivantes