Ottimizzazione delle prestazioni per caricamenti e download con Python
Quando un'applicazione trasferisce i dati usando la libreria client di Archiviazione di Azure per Python, esistono diversi fattori che possono influire sulla velocità, sull'utilizzo della memoria e persino sull'esito positivo o negativo della richiesta. Per ottimizzare le prestazioni e l'affidabilità per i trasferimenti di dati, è importante essere proattivi nella configurazione delle opzioni di trasferimento della libreria client in base all'ambiente in cui viene eseguita l'app.
Questo articolo illustra diverse considerazioni per l'ottimizzazione delle opzioni di trasferimento dei dati. Se ottimizzata correttamente, la libreria client può distribuire in modo efficiente i dati tra più richieste, con conseguente miglioramento della velocità operativa, dell'utilizzo della memoria e della stabilità di rete.
Ottimizzazione delle prestazioni per i caricamenti
L'ottimizzazione corretta delle opzioni di trasferimento dei dati è fondamentale per ottenere prestazioni affidabili per i caricamenti. I trasferimenti di archiviazione vengono partizionati in diversi sottotrasferimenti in base ai valori di questi argomenti. Le dimensioni massime di trasferimento supportate variano in base all'operazione e alla versione del servizio, quindi assicurarsi di controllare la documentazione per determinare i limiti. Per altre informazioni sui limiti delle dimensioni di trasferimento per l'archiviazione BLOB, vedere Dimensionare le destinazioni per l'archiviazione BLOB.
Impostare le opzioni di trasferimento per i caricamenti
Gli argomenti seguenti possono essere ottimizzati in base alle esigenze dell'app:
- max_single_put_size: dimensione massima per il caricamento di un BLOB con una singola richiesta. Il valore predefinito è 64 MiB.
- max_block_size: la lunghezza massima di un trasferimento in byte durante il caricamento di un BLOB in blocchi in parti. Il valore predefinito è 4 MiB.
max_concurrency
: numero massimo di sottotrasferimenti utilizzabili in parallelo.
Nota
Le librerie client useranno le impostazioni predefinite per ogni opzione di trasferimento dei dati, se non specificato altrimenti. Queste impostazioni predefinite sono in genere efficienti in un ambiente data center, ma non sono adatte per gli ambienti consumer domestici. Le opzioni di trasferimento dei dati non ottimizzate possono comportare operazioni eccessivamente lunghe e persino timeout delle richieste. È consigliabile essere proattivi nel testare questi valori e ottimizzarli in base alle esigenze dell'applicazione e dell'ambiente.
max_single_put_size
L'argomento max_single_put_size
è la dimensione massima del BLOB in byte per un caricamento di una singola richiesta. Se la dimensione del BLOB è minore o uguale a max_single_put_size
, il BLOB viene caricato con una singola richiesta Put Blob. Se le dimensioni del BLOB sono maggiori di max_single_put_size
o sono sconosciute, il BLOB viene caricato in blocchi usando una serie di chiamate Put Block seguite da Put Block List.
È importante notare che il valore specificato per max_block_size
non limita il valore definito per max_single_put_size
. L'argomento max_single_put_size
definisce una limitazione delle dimensioni separata per una richiesta in modo da eseguire l'intera operazione contemporaneamente, senza sottotrasferimenti. Spesso si vuole che max_single_put_size
sia almeno grande quanto il valore definito per max_block_size
, se non più grande. A seconda delle dimensioni del trasferimento dei dati, questo approccio può essere più efficiente, poiché il trasferimento viene completato con una singola richiesta ed evita il sovraccarico di più richieste.
Se non si è certi del valore migliore per la situazione, un'opzione sicura consiste nell'impostare max_single_put_size
sullo stesso valore usato per max_block_size
.
max_block_size
L'argomento max_block_size
è la lunghezza massima di un trasferimento in byte durante il caricamento di un BLOB in blocchi in parti. Come accennato in precedenza, questo valore non limita max_single_put_size
, che può essere maggiore di max_block_size
.
Per mantenere efficiente lo spostamento dei dati, le librerie client potrebbero non raggiungere sempre il valore max_block_size
per ogni trasferimento. A seconda dell'operazione, il valore massimo supportato per le dimensioni del trasferimento può variare. Per altre informazioni sui limiti delle dimensioni di trasferimento per l'archiviazione BLOB, vedere il grafico in Dimensionare le destinazioni per l'archiviazione BLOB.
Esempio di codice
L'esempio di codice seguente mostra come specificare le opzioni di trasferimento dei dati durante la creazione di un oggetto BlobClient
e come caricare i dati usando tale oggetto client. I valori forniti in questo esempio non sono necessariamente quelli consigliati. Per ottimizzare correttamente questi valori, è necessario considerare le esigenze specifiche dell'app.
def upload_blob_transfer_options(self, account_url: str, container_name: str, blob_name: str):
# Create a BlobClient object with data transfer options for upload
blob_client = BlobClient(
account_url=account_url,
container_name=container_name,
blob_name=blob_name,
credential=DefaultAzureCredential(),
max_block_size=1024*1024*4, # 4 MiB
max_single_put_size=1024*1024*8 # 8 MiB
)
with open(file=os.path.join(r'file_path', blob_name), mode="rb") as data:
blob_client = blob_client.upload_blob(data=data, overwrite=True, max_concurrency=2)
In questo esempio viene impostato il numero di ruoli di lavoro di trasferimento paralleli su 2, usando l'argomento max_concurrency
nella chiamata al metodo. Questa configurazione si apre contemporaneamente a due connessioni, consentendo il caricamento in parallelo. Durante la creazione di istanze del client, l'argomento max_single_put_size
viene impostato su 8 MiB. Se le dimensioni del BLOB sono inferiori a 8 MiB, è necessaria solo una singola richiesta per completare l'operazione di caricamento. Se le dimensioni del BLOB sono maggiori di 8 MiB, il BLOB viene caricato in blocchi con una dimensione massima di 4 MiB, come impostato dall'argomento max_block_size
.
Considerazioni sulle prestazioni per i caricamenti
Durante un caricamento, le librerie client di archiviazione suddividono un determinato flusso di caricamento in più sottocaricamenti in base alle opzioni di configurazione definite durante la costruzione del cliente. Ogni sottocaricamento ha una propria chiamata dedicata all'operazione REST. Per un oggetto BlobClient
, questa operazione è Put Block. La libreria client di archiviazione gestisce queste operazioni REST in parallelo (a seconda delle opzioni di trasferimento) per completare il caricamento.
Per informazioni su come la libreria client gestisce il buffering consultare le sezioni seguenti.
Nota
I BLOB in blocchi hanno un numero massimo di 50.000 blocchi. Le dimensioni massime del BLOB in blocchi, quindi, sono pari a 50.000 volte max_block_size
.
Buffering durante i caricamenti
Il livello REST di archiviazione non supporta la ripresa di un'operazione di caricamento REST che è stata interrotta. I singoli trasferimenti vengono completati o persi. Per garantire la resilienza per i caricamenti di flussi, le librerie client di archiviazione eseguono il buffer dei dati per ogni singola chiamata REST prima di avviare il caricamento. Oltre alle limitazioni della velocità di rete, questo comportamento di buffering è un motivo per considerare un valore più piccolo per max_block_size
, anche quando si effettuano caricamenti in sequenza. La riduzione del valore di max_block_size
riduce la quantità massima di dati memorizzati nel buffer per ogni richiesta e per ogni retry di una richiesta non riuscita. Se si verificano timeout frequenti durante i trasferimenti di dati di una determinata dimensione, riducendo il valore di max_block_size
si riduce il tempo di memorizzazione nel buffer e si possono ottenere prestazioni migliori.
Per impostazione predefinita, l'SDK memorizza nel buffer i dati di max_block_size
byte per ogni richiesta di sottocaricamento simultanea, ma l'uso della memoria può essere limitato a 4 MiB per richiesta se vengono soddisfatte le condizioni seguenti:
- L'argomento
max_block_size
deve essere maggiore dimin_large_block_upload_threshold
. L'argomentomin_large_block_upload_threshold
può essere definito durante la creazione di istanze client ed è la dimensione minima del blocco in byte necessaria per usare l'algoritmo efficiente per la memoria. Il valore predefinito dell'argomentomin_large_block_upload_threshold
è4*1024*1024 + 1
. - Il flusso fornito deve essere ricercabile. Un flusso ricercabile è un flusso che supporta l'esecuzione di query e la modifica della posizione corrente all'interno di un flusso stesso.
- Il BLOB deve essere un BLOB in blocchi.
Anche se questa strategia si applica alla maggior parte delle situazioni, è comunque possibile che si verifichi un maggiore buffering se il codice usa altre funzionalità della libreria client che richiedono il buffering.
Ottimizzazione delle prestazioni per i download
L'ottimizzazione corretta delle opzioni di trasferimento dei dati è fondamentale per ottenere prestazioni affidabili per i download. I trasferimenti di archiviazione vengono partizionati in diversi sottotrasferimenti in base ai valori di questi argomenti.
Impostare le opzioni di trasferimento per i download
Gli argomenti seguenti possono essere ottimizzati in base alle esigenze dell'app:
max_chunk_get_size
: dimensioni massime del blocco da usare per il download di un BLOB. Il valore predefinito è 4 MiB.max_concurrency
: numero massimo di sottotrasferimenti utilizzabili in parallelo.max_single_get_size
: dimensioni massime per eseguire il download di un BLOB in una singola chiamata. Se le dimensioni totali del BLOB superanomax_single_get_size
, il resto dei dati BLOB viene scaricato in blocchi. Il valore predefinito è 32 MiB.
Esempio di codice
def download_blob_transfer_options(self, account_url: str, container_name: str, blob_name: str):
# Create a BlobClient object with data transfer options for download
blob_client = BlobClient(
account_url=account_url,
container_name=container_name,
blob_name=blob_name,
credential=DefaultAzureCredential(),
max_single_get_size=1024*1024*32, # 32 MiB
max_chunk_get_size=1024*1024*4 # 4 MiB
)
with open(file=os.path.join(r'file_path', 'file_name'), mode="wb") as sample_blob:
download_stream = blob_client.download_blob(max_concurrency=2)
sample_blob.write(download_stream.readall())
Considerazioni sulle prestazioni per i download
Durante un download, le librerie client di archiviazione suddividono una determinata richiesta di download in più download secondari in base alle opzioni di configurazione definite durante la costruzione del client. Ogni sottodownload ha una propria chiamata dedicata all'operazione REST. A seconda delle opzioni di trasferimento, le librerie client gestiscono queste operazioni REST in parallelo per completare il download.
max_single_get_size per i download
Durante un download, le librerie client di archiviazione effettuano una richiesta di intervallo di download usando max_single_get_size
prima di eseguire qualsiasi altra operazione. Durante questa richiesta di download iniziale, le librerie client conoscono le dimensioni totali della risorsa. Se la richiesta iniziale ha scaricato tutto il contenuto, l'operazione viene completata. In caso contrario, le librerie client continuano a effettuare richieste di intervallo fino a max_chunk_get_size
, fino al completamento del download.
Passaggi successivi
- Questo articolo fa parte della Guida per sviluppatori di Archiviazione BLOB per Python. Vedere l’elenco completo degli articoli della guida per sviluppatori in Creare la propria app.
- Per altre informazioni sui fattori che possono influenzare le prestazioni per le operazioni di Archiviazione di Azure, vedere Latenza nell'archiviazione BLOB.
- Per un elenco delle considerazioni di progettazione per ottimizzare le prestazioni per le app che usano l'archiviazione BLOB, vedere Elenco di controllo per prestazioni e scalabilità dell'archiviazione BLOB.