Cloud Profiler ile üretim performansını analiz etme

1. Genel Bakış

İstemci uygulaması ve ön uç web geliştiricileri, kodlarının performansını artırmak için genellikle Android Studio CPU Profiler veya Chrome'da bulunan profil oluşturma araçları gibi araçları kullanır. Ancak arka uç hizmetleri üzerinde çalışanlar, benzer tekniklere neredeyse hiç erişememiş veya bu teknikleri benimsememiştir. Cloud Profiler, kodlarının Google Cloud Platform'da veya başka bir yerde çalışıp çalışmadığına bakılmaksızın, hizmet geliştiricilere bu özelliklerin aynısını sunar.

95c034c70c9cac22.png

Araç, üretim uygulamalarınızdan CPU kullanımı ve bellek ayırma bilgilerini toplar. Bu bilgileri uygulamanın kaynak koduyla ilişkilendirerek en çok kaynağı tüketen uygulama bölümlerini belirlemenize yardımcı olur ve kodun performans özelliklerini aydınlatır. Araç tarafından kullanılan toplama tekniklerinin düşük ek yükü, aracı üretim ortamlarında sürekli kullanıma uygun hale getirir.

Bu codelab'de, Go programı için Cloud Profiler'ı nasıl ayarlayacağınızı ve aracın uygulama performansı hakkında ne tür analizler sunabileceğini öğreneceksiniz.

Neler öğreneceksiniz?

  • Cloud Profiler ile profilleme için Go programını yapılandırma
  • Cloud Profiler ile performans verilerini toplama, görüntüleme ve analiz etme

Gerekenler

  • Google Cloud Platform projesi
  • Chrome veya Firefox gibi bir tarayıcı
  • Vim, EMACs veya Nano gibi standart Linux metin düzenleyicileri hakkında bilgi sahibi olmanız gerekir.

Bu eğiticiden nasıl yararlanacaksınız?

Yalnızca okuyun Okuyun ve alıştırmaları tamamlayın

Google Cloud Platform deneyiminizi nasıl değerlendirirsiniz?

Başlangıç Orta İleri

2. Kurulum ve Gereksinimler

Yönlendirmesiz ortam kurulumu

  1. Cloud Console'da oturum açın ve yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanın. Gmail veya Google Workspace hesabınız yoksa hesap oluşturmanız gerekir.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

Proje kimliğini unutmayın. Bu kimlik, tüm Google Cloud projelerinde benzersiz bir addır (Yukarıdaki ad zaten alınmış olduğundan sizin için çalışmayacaktır). Bu codelab'in ilerleyen kısımlarında PROJECT_ID olarak adlandırılacaktır.

  1. Ardından, Google Cloud kaynaklarını kullanmak için Cloud Console'da faturalandırmayı etkinleştirmeniz gerekir.

Bu codelab'i tamamlamak neredeyse hiç maliyetli değildir. Bu eğitimin ötesinde faturalandırma ücreti alınmaması için kaynakları nasıl kapatacağınız konusunda size tavsiyelerde bulunan "Temizleme" bölümündeki talimatları uyguladığınızdan emin olun. Google Cloud'un yeni kullanıcıları 300 ABD doları değerinde ücretsiz deneme programından yararlanabilir.

Google Cloud Shell

Google Cloud, dizüstü bilgisayarınızdan uzaktan çalıştırılabilir. Ancak bu codelab'de kurulumu basitleştirmek için bulutta çalışan bir komut satırı ortamı olan Google Cloud Shell'i kullanacağız.

Cloud Shell'i etkinleştirme

  1. Cloud Console'da Cloud Shell'i etkinleştir 'i 4292cbf4971c9786.png tıklayın.

bce75f34b2c53987.png

Cloud Shell'i daha önce hiç başlatmadıysanız ne olduğunu açıklayan bir ara ekran (ekranın alt kısmı) gösterilir. Bu durumda Devam'ı tıkladığınızda bu ekranı bir daha görmezsiniz. Bu tek seferlik ekran aşağıdaki gibi görünür:

70f315d7b402b476.png

Cloud Shell'in temel hazırlığı ve bağlanması yalnızca birkaç dakikanızı alır.

fbe3a0674c982259.png

Bu sanal makine, ihtiyaç duyduğunuz tüm geliştirme araçlarını içerir. 5 GB boyutunda kalıcı bir ana dizin bulunur ve Google Cloud'da çalışır. Bu sayede ağ performansı ve kimlik doğrulama önemli ölçüde güçlenir. Bu codelab'deki çalışmalarınızın neredeyse tamamını yalnızca bir tarayıcı veya Chromebook'unuzla yapabilirsiniz.

Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını ve projenin, proje kimliğinize ayarlandığını görürsünüz.

  1. Kimliğinizin doğrulandığını onaylamak için Cloud Shell'de şu komutu çalıştırın:
gcloud auth list

Komut çıkışı

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. gcloud komutunun projeniz hakkında bilgi sahibi olduğunu onaylamak için Cloud Shell'de aşağıdaki komutu çalıştırın:
gcloud config list project

Komut çıkışı

[core]
project = <PROJECT_ID>

Değilse şu komutla ayarlayabilirsiniz:

gcloud config set project <PROJECT_ID>

Komut çıkışı

Updated property [core/project].

3. Cloud Profiler'a gitme

Cloud Console'da, sol gezinme çubuğunda "Profiler"ı tıklayarak Profil Oluşturucu kullanıcı arayüzüne gidin:

37ad0df7ddb2ad17.png

Alternatif olarak, Profiler kullanıcı arayüzüne gitmek için Cloud Console arama çubuğunu da kullanabilirsiniz. "Cloud Profiler" yazıp bulunan öğeyi seçmeniz yeterlidir. Her iki durumda da aşağıdakine benzer şekilde "Görüntülenecek veri yok" mesajını içeren Profiler kullanıcı arayüzünü görürsünüz. Proje yeni olduğundan henüz profil oluşturma verisi toplanmamıştır.

d275a5f61ed31fb2.png

Şimdi profil oluşturma zamanı.

4. Karşılaştırmayı Profillendirme

Github'da bulunan basit bir sentetik Go uygulaması kullanacağız. Hâlâ açık olan Cloud Shell terminalinde (ve Profiler kullanıcı arayüzünde "Gösterilecek veri yok" mesajı gösterilirken) aşağıdaki komutu çalıştırın:

$ go get -u github.com/GoogleCloudPlatform/golang-samples/profiler/...

Ardından uygulama dizinine geçin:

$ cd ~/gopath/src/github.com/GoogleCloudPlatform/golang-samples/profiler/hotapp

Dizin, profilleme aracının etkinleştirildiği sentetik bir uygulama olan "main.go" dosyasını içerir:

main.go

...
import (
        ...
        "cloud.google.com/go/profiler"
)
...
func main() {
        err := profiler.Start(profiler.Config{
                Service:        "hotapp-service",
                DebugLogging:   true,
                MutexProfiling: true,
        })
        if err != nil {
                log.Fatalf("failed to start the profiler: %v", err)
        }
        ...
}

Profil oluşturma aracısı varsayılan olarak CPU, yığın ve iş parçacığı profillerini toplar. Buradaki kod, mutex (çakışma olarak da bilinir) profillerinin toplanmasını sağlar.

Şimdi programı çalıştırın:

$ go run main.go

Program çalışırken profilleme aracısı, yapılandırılan beş türün profillerini düzenli olarak toplar. Toplama işlemi zaman içinde rastgele yapılır (her tür için ortalama hız dakikada bir profildir). Bu nedenle, her türün toplanması üç dakikaya kadar sürebilir. Program, profil oluşturduğunda sizi bilgilendirir. Mesajlar, yukarıdaki yapılandırmada DebugLogging işaretiyle etkinleştirilir. Aksi takdirde, ajan sessizce çalışır:

$ go run main.go
2018/03/28 15:10:24 profiler has started
2018/03/28 15:10:57 successfully created profile THREADS
2018/03/28 15:10:57 start uploading profile
2018/03/28 15:11:19 successfully created profile CONTENTION
2018/03/28 15:11:30 start uploading profile
2018/03/28 15:11:40 successfully created profile CPU
2018/03/28 15:11:51 start uploading profile
2018/03/28 15:11:53 successfully created profile CONTENTION
2018/03/28 15:12:03 start uploading profile
2018/03/28 15:12:04 successfully created profile HEAP
2018/03/28 15:12:04 start uploading profile
2018/03/28 15:12:04 successfully created profile THREADS
2018/03/28 15:12:04 start uploading profile
2018/03/28 15:12:25 successfully created profile HEAP
2018/03/28 15:12:25 start uploading profile
2018/03/28 15:12:37 successfully created profile CPU
...

Profillerden ilki toplandıktan kısa süre sonra kullanıcı arayüzü otomatik olarak güncellenir. Bu işlemden sonra otomatik olarak güncellenmez. Yeni verileri görmek için Profil Oluşturucu kullanıcı arayüzünü manuel olarak yenilemeniz gerekir. Bunu yapmak için zaman aralığı seçicideki Şimdi düğmesini iki kez tıklayın:

650051097b651b91.png

Kullanıcı arayüzü yenilendikten sonra aşağıdakine benzer bir ekran görürsünüz:

47a763d4dc78b6e8.png

Profil türü seçicide, kullanılabilen beş profil türü gösterilir:

b5d7b4b5051687c9.png

Şimdi her bir profil türünü ve bazı önemli kullanıcı arayüzü özelliklerini inceleyelim, ardından bazı denemeler yapalım. Bu aşamada Cloud Shell terminaline artık ihtiyacınız yoktur. Bu nedenle, CTRL-C tuşlarına basıp "exit" yazarak terminalden çıkabilirsiniz.

5. Profiler verilerini analiz etme

Artık bazı veriler topladığımıza göre, bunları daha yakından inceleyelim. Üretimde farklı performans sorunlarının tipik davranışlarını simüle eden sentetik bir uygulama kullanıyoruz (kaynak Github'da mevcuttur).

CPU yoğun kod

CPU profili türünü seçin. Kullanıcı arayüzü yükledikten sonra, alev grafiğinde load işlevi için dört yaprak bloğu görürsünüz. Bu bloklar, CPU tüketiminin tamamını oluşturur:

fae661c9fe6c58df.png

Bu işlev, sıkı bir döngü çalıştırarak çok sayıda CPU döngüsü kullanmak için özel olarak yazılmıştır:

main.go

func load() {
        for i := 0; i < (1 << 20); i++ {
        }
}

İşlev, busyloop() işlevinden dört çağrı yolu üzerinden dolaylı olarak çağrılır: busyloop → {foo1, foo2} → {bar, baz} → load. Bir işlev kutusunun genişliği, belirli çağrı yolunun göreceli maliyetini gösterir. Bu durumda dört yolun maliyeti de yaklaşık olarak aynıdır. Gerçek bir programda, performans açısından en önemli olan görüşme yollarını optimize etmeye odaklanmak istersiniz. Daha büyük kutularla daha maliyetli yolları görsel olarak vurgulayan alev grafiği, bu yolların kolayca tanımlanmasını sağlar.

Görüntülemeyi daha da hassaslaştırmak için profil verileri filtresini kullanabilirsiniz. Örneğin, filtre dizesi olarak "baz"ı belirten bir "Yığınları göster" filtresi eklemeyi deneyin. Aşağıdaki ekran görüntüsüne benzer bir şey görmelisiniz. Burada, load() için dört arama yolundan yalnızca ikisi gösterilir. Bu iki yol, adında "baz" dizesi bulunan bir işlevden geçen tek yollardır. Bu tür filtreleme, daha büyük bir programın bir alt bölümüne odaklanmak istediğinizde (örneğin, yalnızca bir bölümünün sahibi olduğunuz için) kullanışlıdır.

eb1d97491782b03f.png

Bellek Yoğun Kod (Memory-intensive Code)

Şimdi "Heap" profil türüne geçin. Önceki denemelerde oluşturduğunuz tüm filtreleri kaldırdığınızdan emin olun. Artık allocImpl tarafından çağrılan alloc'nin, uygulamadaki ana bellek tüketicisi olarak gösterildiği bir alev grafiği görmelisiniz:

f6311c8c841d04c4.png

Alev grafiğinin üzerindeki özet tablo, uygulamada kullanılan toplam bellek miktarının ortalama ~57,4 MiB olduğunu ve bunun büyük bir kısmının allocImpl işlevi tarafından ayrıldığını gösteriyor. Bu işlevin uygulanması göz önüne alındığında bu durum şaşırtıcı değildir:

main.go

func allocImpl() {
        // Allocate 64 MiB in 64 KiB chunks
        for i := 0; i < 64*16; i++ {
                mem = append(mem, make([]byte, 64*1024))
        }
}

İşlev bir kez yürütülür, daha küçük parçalar halinde 64 MiB ayırır ve ardından bu parçalara yönelik işaretçileri çöp toplama işleminden korunmaları için genel bir değişkende depolar. Profiler tarafından kullanılan bellek miktarının 64 MiB'den biraz farklı olduğunu unutmayın. Go yığın profili oluşturucu istatistiksel bir araç olduğundan ölçümler düşük ek yüke sahiptir ancak bayt açısından doğru değildir. Bu gibi durumlarda% 10'luk bir fark görmeniz sizi şaşırtmamalıdır.

IO yoğun kod

Profil türü seçicide "İş parçacıkları"nı seçerseniz görünüm, genişliğin büyük bir kısmının wait ve waitImpl işlevleri tarafından kullanıldığı bir alev grafiğine dönüşür:

ebd57fdff01dede9.png

Alev grafiğinin üzerindeki özette, wait işlevinden çağrı yığınlarını büyüten 100 goroutine olduğunu görebilirsiniz. Bu beklemeleri başlatan kod şu şekilde göründüğünden bu ifade tamamen doğrudur:

main.go

func main() {
        ...
        // Simulate some waiting goroutines.
        for i := 0; i < 100; i++ {
                go wait()
        }

Bu profil türü, programın beklenmedik bir süre boyunca beklemede (ör. G/Ç) kalıp kalmadığını anlamak için kullanışlıdır. Bu tür çağrı yığınları, CPU süresinin önemli bir bölümünü tüketmedikleri için genellikle CPU profil oluşturucu tarafından örneklenmez. Genellikle ileti dizisi profilleriyle "Yığınları gizle" filtrelerini kullanmak isteyebilirsiniz. Örneğin, gopark, ile biten tüm yığınları gizlemek için. Çünkü bunlar genellikle boşta kalan gorutinlerdir ve G/Ç üzerinde bekleyenlerden daha az ilgi çekicidir.

İş parçacıkları profil türü, programda iş parçacıklarının programın başka bir bölümüne ait bir mutex'i uzun süre beklediği noktaları belirlemeye de yardımcı olabilir ancak bu amaç için aşağıdaki profil türü daha kullanışlıdır.

Çakışma Yoğunluğu Yüksek Kod

Çakışma profili türü, programdaki en çok "istenen" kilitleri tanımlar. Bu profil türü Go programlarında kullanılabilir ancak aracı yapılandırma kodunda "MutexProfiling: true" belirtilerek açıkça etkinleştirilmelidir. Toplama işlemi, belirli bir kilit bir gorutin A tarafından açılırken başka bir gorutin B'nin kilidin açılmasını beklediği zamanların sayısını ("Çekişmeler" metriği altında) kaydederek çalışır. Ayrıca, engellenen goroutine'in kilidi beklediği süreyi de ("Gecikme" metriği altında) kaydeder. Bu örnekte, tek bir çekişme yığını vardır ve kilidin toplam bekleme süresi 10,5 saniyedir:

83f00dca4a0f768e.png

Bu profili oluşturan kod, bir mutex üzerinde kavga eden 4 goroutineden oluşur:

main.go

func contention(d time.Duration) {
        contentionImpl(d)
}

func contentionImpl(d time.Duration) {
        for {
                mu.Lock()
                time.Sleep(d)
                mu.Unlock()
        }
}
...
func main() {
        ...
        for i := 0; i < 4; i++ {
                go contention(time.Duration(i) * 50 * time.Millisecond)
        }
}

6. Özet

Bu laboratuvarda, bir Go programının Cloud Profiler ile kullanılmak üzere nasıl yapılandırılacağını öğrendiniz. Ayrıca bu araçla performans verilerini nasıl toplayacağınızı, görüntüleyeceğinizi ve analiz edeceğinizi de öğrendiniz. Artık yeni becerinizi Google Cloud Platform'da çalıştırdığınız gerçek hizmetlere uygulayabilirsiniz.

7. Tebrikler!

Cloud Profiler'ı nasıl yapılandıracağınızı ve kullanacağınızı öğrendiniz.

Daha Fazla Bilgi

Lisans

Bu çalışma, Creative Commons Attribution 2.0 Genel Amaçlı Lisans ile lisans altına alınmıştır.