Ottimizzare un'app Go
In questo tutorial, esegui il deployment di un'applicazione Go intenzionalmente inefficiente configurata per raccogliere i dati del profilo. Utilizzi l'interfaccia di Profiler per visualizzare i dati del profilo e identificare le potenziali ottimizzazioni. Modifichi l'applicazione, ne esegui il deployment e valuti l'effetto della modifica.
Prima di iniziare
- Accedi al tuo Google Cloud account. Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei workload.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Abilita l'API Cloud Profiler.
Ruoli richiesti per abilitare le API
Per abilitare le API, devi disporre del ruolo IAM Amministratore utilizzo servizi (
roles/serviceusage.serviceUsageAdmin), che contiene l'autorizzazioneserviceusage.services.enable. Scopri come concedere i ruoli. - Per aprire Cloud Shell, nella barra degli strumenti della Google Cloud console, fai clic su
Attiva Cloud Shell:

Dopo qualche istante, si apre una sessione di Cloud Shell all'interno della Google Cloud console:

Applicazione di esempio
L'obiettivo principale è massimizzare il numero di query al secondo che il server può elaborare. Un obiettivo secondario è ridurre la memoria utilizzata eliminando le allocazioni di memoria non necessarie.
Il server, che utilizza un framework gRPC, riceve una parola o una frase e restituisce il numero di volte in cui la parola o la frase appare nelle opere di Shakespeare.
Il numero medio di query al secondo che il server può gestire viene determinato dal test di carico del server. Per ogni round di test, viene chiamato un simulatore client e gli viene chiesto di emettere 20 query sequenziali. Al termine di un round, vengono visualizzati il numero di query inviate dal simulatore client, il tempo trascorso e il numero medio di query al secondo.
Il codice del server è intenzionalmente inefficiente.
Eseguire l'applicazione di esempio
Scarica ed esegui l'applicazione di esempio:
In Cloud Shell, esegui questi comandi:
git clone https://github.com/GoogleCloudPlatform/golang-samples.git cd golang-samples/profiler/shakesappEsegui l'applicazione con la versione impostata su
1e il numero di round impostato su 15:go run . -version 1 -num_rounds 15Dopo un minuto o due, vengono visualizzati i dati del profilo. I dati del profilo sono simili all'esempio seguente:
Nello screenshot, nota che Tipo di profilo è impostato su
CPU time. Ciò indica che i dati sull'utilizzo della CPU vengono visualizzati nel grafico a fiamme.Di seguito è riportato un output di esempio stampato in Cloud Shell:
$ go run . -version 1 -num_rounds 15 2020/08/27 17:27:34 Simulating client requests, round 1 2020/08/27 17:27:34 Stackdriver Profiler Go Agent version: 20200618 2020/08/27 17:27:34 profiler has started 2020/08/27 17:27:34 creating a new profile via profiler service 2020/08/27 17:27:51 Simulated 20 requests in 17.3s, rate of 1.156069 reqs / sec 2020/08/27 17:27:51 Simulating client requests, round 2 2020/08/27 17:28:10 Simulated 20 requests in 19.02s, rate of 1.051525 reqs / sec 2020/08/27 17:28:10 Simulating client requests, round 3 2020/08/27 17:28:29 Simulated 20 requests in 18.71s, rate of 1.068947 reqs / sec ... 2020/08/27 17:44:32 Simulating client requests, round 14 2020/08/27 17:46:04 Simulated 20 requests in 1m32.23s, rate of 0.216849 reqs / sec 2020/08/27 17:46:04 Simulating client requests, round 15 2020/08/27 17:47:52 Simulated 20 requests in 1m48.03s, rate of 0.185134 reqs / sec
L'output di Cloud Shell mostra il tempo trascorso per ogni iterazione e il tasso di richieste medio. Quando l'applicazione viene avviata, la voce "Simulated 20 requests in 17.3s, rate of 1.156069 reqs / sec" indica che il server esegue circa 1 richiesta al secondo. Nell'ultimo round, la voce "Simulated 20 requests in 1m48.03s, rate of 0.185134 reqs / sec" indica che il server esegue circa 1 richiesta ogni 5 secondi.
Utilizzare i profili del tempo di CPU per massimizzare le query al secondo
Un approccio per massimizzare il numero di query al secondo consiste nell'identificare i metodi che richiedono un uso intensivo della CPU e ottimizzarne le implementazioni. In questa sezione, utilizzi i profili del tempo di CPU per identificare un metodo che richiede un uso intensivo della CPU nel server.
Identificare l'utilizzo del tempo di CPU
Il frame radice del grafico a fiamme elenca il tempo di CPU totale utilizzato dall'applicazione nell'intervallo di raccolta di 10 secondi:
In questo esempio, il servizio ha utilizzato 2.37 s. Quando il sistema viene eseguito su un singolo core, un utilizzo del tempo di CPU di 2,37 secondi corrisponde a un utilizzo del 23,7% di quel core. Per saperne di più, consulta
Tipi di profilazione disponibili.
Modificare l'applicazione
Valutare la modifica
Per valutare la modifica:
Esegui l'applicazione con la versione dell'applicazione impostata su
2:go run . -version 2 -num_rounds 40Una sezione successiva mostra che, con l'ottimizzazione, il tempo necessario per eseguire un singolo round è molto inferiore a quello dell'applicazione non modificata. Per garantire che l'applicazione venga eseguita per un periodo di tempo sufficiente per raccogliere e caricare i profili, il numero di round viene aumentato.
Attendi il completamento dell'applicazione, quindi visualizza i dati del profilo per questa versione dell'applicazione:
- Fai clic su ORA per caricare i dati del profilo più recenti. Per saperne di più, consulta Intervallo di tempo.
- Nel menu Versione, seleziona 2.
Ad esempio, il grafico a fiamme è il seguente:
In questa figura, il frame radice mostra un valore di 7.8 s. A seguito della modifica della funzione di corrispondenza delle stringhe, il tempo di CPU utilizzato dall'applicazione è aumentato da 2,37 secondi a 7,8 secondi, ovvero l'applicazione è passata dall'utilizzo del 23,7% di un core della CPU all'utilizzo del 78% di un core della CPU.
La larghezza del frame è una misura proporzionale dell'utilizzo del tempo di CPU. In questo esempio, la larghezza del frame per GetMatchCount indica che la funzione utilizza circa il 49% di tutto il tempo di CPU utilizzato dall'applicazione.
Nel grafico a fiamme originale, questo stesso frame era circa il 72% della larghezza del grafico.
Per visualizzare l'utilizzo esatto del tempo di CPU, puoi utilizzare la descrizione comando del frame oppure utilizzare
l'Elenco delle funzioni di stato attivo:
L'output in Cloud Shell mostra che la versione modificata completa circa 5,8 richieste al secondo:
$ go run . -version 2 -num_rounds 40 2020/08/27 18:21:40 Simulating client requests, round 1 2020/08/27 18:21:40 Stackdriver Profiler Go Agent version: 20200618 2020/08/27 18:21:40 profiler has started 2020/08/27 18:21:40 creating a new profile via profiler service 2020/08/27 18:21:44 Simulated 20 requests in 3.67s, rate of 5.449591 reqs / sec 2020/08/27 18:21:44 Simulating client requests, round 2 2020/08/27 18:21:47 Simulated 20 requests in 3.72s, rate of 5.376344 reqs / sec 2020/08/27 18:21:47 Simulating client requests, round 3 2020/08/27 18:21:51 Simulated 20 requests in 3.58s, rate of 5.586592 reqs / sec ... 2020/08/27 18:23:51 Simulating client requests, round 39 2020/08/27 18:23:54 Simulated 20 requests in 3.46s, rate of 5.780347 reqs / sec 2020/08/27 18:23:54 Simulating client requests, round 40 2020/08/27 18:23:58 Simulated 20 requests in 3.4s, rate of 5.882353 reqs / sec
La piccola modifica all'applicazione ha avuto due effetti diversi:
Il numero di richieste al secondo è aumentato da meno di 1 al secondo a 5,8 al secondo.
Il tempo di CPU per richiesta, calcolato dividendo l'utilizzo della CPU per il numero di richieste al secondo, è diminuito dal 23,7% al 13,4%.
Tieni presente che il tempo di CPU per richiesta è diminuito anche se l'utilizzo del tempo di CPU è aumentato da 2,37 secondi, che corrisponde a un utilizzo del 23,7% di un singolo core della CPU, a 7,8 secondi, ovvero il 78% di un core della CPU.
Utilizzare i profili heap allocati per migliorare l'utilizzo delle risorse
Questa sezione illustra come utilizzare i profili heap e heap allocati per identificare un metodo che richiede un uso intensivo dell'allocazione nell'applicazione:
I profili heap mostrano la quantità di memoria allocata nell'heap del programma nell'istante in cui viene raccolto il profilo.
I profili heap allocati mostrano la quantità totale di memoria allocata nell'heap del programma durante l'intervallo in cui è stato raccolto il profilo. Dividendo questi valori per 10 secondi, l'intervallo di raccolta dei profili, puoi interpretarli come frequenze di allocazione.
Abilitare la raccolta dei profili heap
Esegui l'applicazione con la versione dell'applicazione impostata su
3e abilita la raccolta dei profili heap e heap allocati.go run . -version 3 -num_rounds 40 -heap -heap_allocAttendi il completamento dell'applicazione, quindi visualizza i dati del profilo per questa versione dell'applicazione:
- Fai clic su ORA per caricare i dati del profilo più recenti.
- Nel menu Versione, seleziona 3.
- Nel menu Tipo di Profiler, seleziona Heap allocato.
Ad esempio, il grafico a fiamme è il seguente:
Identificare la frequenza di allocazione heap
Il frame radice mostra la quantità totale di heap allocata durante i 10 secondi in cui è stato raccolto un profilo, in media su tutti i profili. In questo esempio, il frame radice mostra che, in media, sono stati allocati 1,535 GiB di memoria.
Modificare l'applicazione
Valutare la modifica
Per valutare la modifica:
Esegui l'applicazione con la versione dell'applicazione impostata su
4:go run . -version 4 -num_rounds 60 -heap -heap_allocAttendi il completamento dell'applicazione, quindi visualizza i dati del profilo per questa versione dell'applicazione:
- Fai clic su ORA per caricare i dati del profilo più recenti.
- Nel menu Versione, seleziona 4.
- Nel menu Tipo di Profiler, seleziona Heap allocato.
Per quantificare l'effetto della modifica di
readFilessulla frequenza di allocazione heap, confronta i profili heap allocati per la versione 4 con quelli raccolti per la versione 3:
La descrizione comando del frame radice mostra che con la versione 4 la quantità media di memoria allocata durante la raccolta dei profili è diminuita di 1,301 GiB rispetto alla versione 3. La descrizione comando per
readFiles.func1mostra una diminuzione di 1,045 GiB:
Per quantificare l'effetto sulla garbage collection, configura un confronto dei profili del tempo di CPU. Nello screenshot seguente, viene applicato un filtro per mostrare gli stack per il garbage collector Go
runtime.gcBgMarkWorker.*. Lo screenshot mostra che l'utilizzo della CPU per la garbage collection è ridotto dal 16,8% al 4,97%.
Per determinare se la modifica ha un impatto sul numero di richieste al secondo gestite dall'applicazione, visualizza l'output in Cloud Shell. In questo esempio, la versione 4 completa fino a 15 richieste al secondo, un valore notevolmente superiore alle 5,8 richieste al secondo della versione 3:
$ go run . -version 4 -num_rounds 60 -heap -heap_alloc 2020/08/27 21:51:42 Simulating client requests, round 1 2020/08/27 21:51:42 Stackdriver Profiler Go Agent version: 20200618 2020/08/27 21:51:42 profiler has started 2020/08/27 21:51:42 creating a new profile via profiler service 2020/08/27 21:51:44 Simulated 20 requests in 1.47s, rate of 13.605442 reqs / sec 2020/08/27 21:51:44 Simulating client requests, round 2 2020/08/27 21:51:45 Simulated 20 requests in 1.3s, rate of 15.384615 reqs / sec 2020/08/27 21:51:45 Simulating client requests, round 3 2020/08/27 21:51:46 Simulated 20 requests in 1.31s, rate of 15.267176 reqs / sec ...
L'aumento delle query al secondo gestite dall'applicazione potrebbe essere dovuto al minor tempo dedicato alla garbage collection.
Puoi comprendere meglio l'effetto della modifica di
readFilesvisualizzando i profili heap. Un confronto dei profili heap per la versione 4 con quelli della versione 3 mostra che l'utilizzo dell'heap è diminuito da 70,95 MiB a 18,47 MiB:
Riepilogo
In questa guida rapida, sono stati utilizzati i profili del tempo di CPU e dell'heap allocato per identificare le potenziali ottimizzazioni di un'applicazione. Gli obiettivi erano massimizzare il numero di richieste al secondo ed eliminare le allocazioni non necessarie.
Utilizzando i profili del tempo di CPU, è stata identificata una funzione che richiede un uso intensivo della CPU. Dopo aver applicato una semplice modifica, il tasso di richieste del server è aumentato a 5,8 al secondo, rispetto a circa 1 al secondo.
Utilizzando i profili heap allocati, la funzione
shakesapp/server.goreadFilesè stata identificata come avente una frequenza di allocazione elevata. Dopo aver ottimizzatoreadFiles, il tasso di richieste del server è aumentato a 15 richieste al secondo e la quantità media di memoria allocata durante la raccolta dei profili di 10 secondi è diminuita di 1,301 GiB.
Passaggi successivi
Per informazioni su come vengono raccolti e inviati i profili al tuo Google Cloud progetto, vedi Raccolta dei profili.
Leggi le nostre risorse su DevOps ed esplora il nostro programma di ricerca.
- Profilazione delle applicazioni Go
- Profilazione delle applicazioni Java
- Profilazione delle applicazioni Node.js
- Profilazione delle applicazioni Python
- Profilazione delle applicazioni in esecuzione all'esterno Google Cloud