Profiling

CPU Profiling

CPU profilinin julia kodunu analiz etmenin iki ana yaklaşımı vardır:

Via @profile

Veri bir çağrı için @profile makrosu aracılığıyla profil oluşturmanın etkin olduğu yer.

julia> using Profile

julia> @profile foo()

julia> Profile.print()
Overhead ╎ [+additional indent] Count File:Line; Function
=========================================================
    ╎147  @Base/client.jl:506; _start()
        ╎ 147  @Base/client.jl:318; exec_options(opts::Base.JLOptions)
...

Triggered During Execution

Zaten çalışan görevler, kullanıcı tarafından tetiklenen herhangi bir zamanda sabit bir süre boyunca da profil oluşturulabilir.

Profiling'i tetiklemek için:

  • MacOS ve FreeBSD (BSD tabanlı platformlar): ctrl-t kullanın veya julia sürecine bir SIGINFO sinyali gönderin, yani % kill -INFO $julia_pid
  • Linux: julia sürecine SIGUSR1 sinyali gönderin, yani % kill -USR1 $julia_pid
  • Windows: Şu anda desteklenmiyor.

İlk olarak, sinyalin atıldığı anda tek bir yığın izinin gösterildiği, ardından 1 saniyelik bir profilin toplandığı ve sonraki yield noktasında profil raporunun verildiği, yield noktaları olmayan kodlar için görev tamamlanmasında (örneğin, sıkı döngüler) olabileceği belirtilmektedir.

İsteğe bağlı olarak, ortam değişkenini JULIA_PROFILE_PEEK_HEAP_SNAPSHOT değerini 1 olarak ayarlayın, böylece otomatik olarak heap snapshot toplayabilirsiniz.

julia> foo()
##== the user sends a trigger while foo is running ==##
load: 2.53  cmd: julia 88903 running 6.16u 0.97s

======================================================================================
Information request received. A stacktrace will print followed by a 1.0 second profile
======================================================================================

signal (29): Information request: 29
__psynch_cvwait at /usr/lib/system/libsystem_kernel.dylib (unknown line)
_pthread_cond_wait at /usr/lib/system/libsystem_pthread.dylib (unknown line)
...

======================================================================
Profile collected. A report will print if the Profile module is loaded
======================================================================

Overhead ╎ [+additional indent] Count File:Line; Function
=========================================================
Thread 1 Task 0x000000011687c010 Total snapshots: 572. Utilization: 100%
   ╎147 @Base/client.jl:506; _start()
       ╎ 147 @Base/client.jl:318; exec_options(opts::Base.JLOptions)
...

Thread 2 Task 0x0000000116960010 Total snapshots: 572. Utilization: 0%
   ╎572 @Base/task.jl:587; task_done_hook(t::Task)
      ╎ 572 @Base/task.jl:879; wait()
...

Customization

Profiling süresini Profile.set_peek_duration aracılığıyla ayarlayabilirsiniz.

Profil raporu, iş parçacığı ve görev bazında ayrılmıştır. Bunu geçersiz kılmak için Profile.peek_report[]'a argüman almayan bir fonksiyon geçirin. Yani, gruplamayı kaldırmak için Profile.peek_report[] = () -> Profile.print() kullanın. Bu, harici bir profil veri tüketicisi tarafından da geçersiz kılınabilir.

Reference

Profile.@profileMacro
@profil

@profil <ifade> ifadenizi periyodik geri izlemeler alarak çalıştırır. Bunlar, geri izlemelerin dahili bir tamponuna eklenir.

source

Profile içindeki yöntemler dışa aktarılmamış ve Profile.print() gibi çağrılması gerekiyor.

Profile.printFunction
print([io::IO = stdout,] [data::Vector = fetch()], [lidict::Union{LineInfoDict, LineInfoFlatDict} = getdict(data)]; kwargs...)

Profiling sonuçlarını ioya (varsayılan olarak stdout) yazdırır. Eğer bir data vektörü sağlamazsanız, birikmiş geri izlerin içsel tamponu kullanılacaktır.

Anahtar argümanlar herhangi bir kombinasyon olabilir:

  • format – Geri izlerin ağaç yapısını gösteren (varsayılan, :tree) veya göstermeyen (:flat) girintili olarak yazdırılıp yazdırılmayacağını belirler.
  • C – Eğer true ise, C ve Fortran kodlarından geri izler gösterilir (normalde hariç tutulur).
  • combine – Eğer true (varsayılan), aynı kod satırına karşılık gelen talimat işaretçileri birleştirilir.
  • maxdepth:tree formatında maxdepth'ten daha derinliği sınırlar.
  • sortedby:flat formatındaki sıralamayı kontrol eder. :filefuncline (varsayılan) kaynak satırına göre sıralar, :count toplanan örnek sayısına göre sıralar ve :overhead her fonksiyonun kendisi tarafından neden olunan örnek sayısına göre sıralar.
  • groupby – Görevler ve iş parçacıkları üzerinde gruplamayı veya gruplama olmamasını kontrol eder. Seçenekler :none (varsayılan), :thread, :task, [:thread, :task] veya [:task, :thread]'dir; son iki seçenek iç içe gruplama sağlar.
  • noisefloor – Örneklerin sezgisel gürültü tabanını aşan çerçeveleri sınırlar (sadece :tree formatına uygulanır). Bunun için denemek için önerilen bir değer 2.0'dır (varsayılan 0'dır). Bu parametre, n <= noisefloor * √N olan satırlar için örnekleri gizler; burada n bu satırdaki örnek sayısı ve N çağrılan için örnek sayısıdır.
  • mincount – Yazdırmayı yalnızca en az mincount kez bulunan satırlarla sınırlar.
  • recur:tree formatındaki özyineleme işlemlerini kontrol eder. :off (varsayılan) ağacı normal olarak yazdırır. :flat bunun yerine herhangi bir özyinelemeyi (ip ile) sıkıştırır ve herhangi bir kendine özyinelemeyi bir yineleyiciye dönüştürmenin yaklaşık etkisini gösterir. :flatc aynı şeyi yapar ancak ayrıca C çerçevelerinin çökmesini de içerir (belirli durumlarda jl_apply etrafında garip şeyler yapabilir).
  • threads::Union{Int,AbstractVector{Int}} – Raporun hangi iş parçacıklarından anlık görüntüler içereceğini belirtir. Bunun, hangi iş parçacıklarında örneklerin toplandığını kontrol etmediğini unutmayın (bu örnekler başka bir makinede de toplanmış olabilir).
  • tasks::Union{Int,AbstractVector{Int}} – Raporun hangi görevlerden anlık görüntüler içereceğini belirtir. Bunun, hangi görevlerde örneklerin toplandığını kontrol etmediğini unutmayın.
Julia 1.8

groupby, threads ve tasks anahtar argümanları Julia 1.8'de tanıtılmıştır.

Note

Windows'ta profil oluşturma ana iş parçacığı ile sınırlıdır. Diğer iş parçacıkları örneklenmemiştir ve raporda görünmeyecektir.

source
print([io::IO = stdout,] data::Vector, lidict::LineInfoDict; kwargs...)

Profiling sonuçlarını io'ya yazdırır. Bu varyant, daha önceki bir retrieve çağrısı ile dışa aktarılan sonuçları incelemek için kullanılır. Geri izlemelerin data vektörünü ve satır bilgileri için bir lidict sözlüğünü sağlayın.

Geçerli anahtar kelime argümanlarının açıklaması için Profile.print([io], data)'ya bakın.

source
Profile.initFunction
init(; n::Integer, delay::Real)

delay arasında geri izleme (saniye cinsinden ölçülen) ve her bir iş parçacığı başına saklanabilecek n talimat işaretçisi sayısını yapılandırın. Her talimat işaretçisi, tek bir kod satırına karşılık gelir; geri izlemeler genellikle uzun bir talimat işaretçisi listesi içerir. Geri izleme başına talimat işaretçileri için 6 boşluk kullanıldığını ve iki NULL son işaretleyicisi saklandığını unutmayın. Mevcut ayarlar, bu işlevi argüman olmadan çağırarak elde edilebilir ve her biri bağımsız olarak anahtar kelimeler kullanılarak veya (n, delay) sırasıyla ayarlanabilir.

source
Profile.fetchFunction
fetch(;include_meta = true) -> data

Profilin geri izleme tamponunun bir kopyasını döndürür. data içindeki değerlerin yalnızca bu makinede ve mevcut oturumda anlamı olduğunu unutmayın, çünkü bu, JIT derlemesinde kullanılan tam bellek adreslerine bağlıdır. Bu işlev esasen dahili kullanım içindir; çoğu kullanıcı için retrieve daha iyi bir seçim olabilir. Varsayılan olarak, threadid ve taskid gibi meta veriler dahildir. Meta verileri kaldırmak için include_meta'yı false olarak ayarlayın.

source
Profile.retrieveFunction
retrieve(; kwargs...) -> data, lidict

"Exports" profil sonuçlarını taşınabilir bir formatta döndürür, tüm geri izleme kümesini (data) ve data içindeki (oturum-spesifik) talimat işaretçilerini LineInfo değerlerine eşleyen bir sözlük döndürür; bu değerler dosya adı, fonksiyon adı ve satır numarasını saklar. Bu fonksiyon, profil sonuçlarını gelecekteki analizler için kaydetmenizi sağlar.

source
Profile.callersFunction
callers(funcname, [data, lidict], [filename=<filename>], [linerange=<start:stop>]) -> Vector{Tuple{count, lineinfo}}

Önceki bir profil çalışmasından, belirli bir fonksiyonu kimin çağırdığını belirleyin. Dosya adını (ve isteğe bağlı olarak, fonksiyonun tanımlandığı satır numaraları aralığını) sağlamak, aşırı yüklenmiş bir yöntemi ayırt etmenizi sağlar. Döndürülen değer, çağrı sayısını ve çağıranın satır bilgilerini içeren bir vektördür. İsteğe bağlı olarak, retrieve ile elde edilen geri izleme data sağlanabilir; aksi takdirde, mevcut iç profil tamponu kullanılır.

source
Profile.clear_malloc_dataFunction
clear_malloc_data()

--track-allocation ile julia çalıştırırken saklanan herhangi bir bellek tahsis verisini temizler. Test etmek istediğiniz komut(lar)ı çalıştırın (JIT derlemesini zorlamak için), ardından clear_malloc_data çağrısını yapın. Ardından komut(lar)ınızı tekrar çalıştırın, Julia'dan çıkın ve ortaya çıkan *.mem dosyalarını inceleyin.

source
Profile.get_peek_durationFunction
get_peek_duration()

SIGINFO veya SIGUSR1 aracılığıyla tetiklenen "peek" profilinin süresini saniye cinsinden alır, platforma bağlı olarak.

source
Profile.set_peek_durationFunction
set_peek_duration(t::Float64)

SIGINFO veya SIGUSR1'e bağlı olarak, platforma göre tetiklenen "peek" profilinin süresini saniye cinsinden ayarlayın.

source

Memory profiling

Profile.Allocs.@profileMacro
Profile.Allocs.@profile [örnek_oranı=0.1] expr

expr sırasında gerçekleşen profil tahsisatlarını profil alır, hem sonucu hem de AllocResults yapısını döndürür.

1.0'lık bir örnek oranı her şeyi kaydedecektir; 0.0 hiçbir şeyi kaydetmeyecektir.

julia> Profile.Allocs.@profile örnek_oranı=0.01 peakflops()
1.03733270279065e11

julia> sonuçlar = Profile.Allocs.fetch()

julia> last(sort(sonuçlar.allocs, by=x->x.size))
Profile.Allocs.Alloc(Vector{Any}, Base.StackTraces.StackFrame[_new_array_ at array.c:127, ...], 5576)

Daha fazla bilgi için Julia belgelerindeki profil alma kılavuzuna bakın.

Julia 1.11

Daha eski Julia sürümleri tüm durumlarda türleri yakalayamazdı. Daha eski Julia sürümlerinde, Profile.Allocs.UnknownType türünde bir tahsisat görüyorsanız, bu, profilcinin tahsis edilen nesnenin türünü bilmediği anlamına gelir. Bu, esasen tahsisatın derleyici tarafından üretilen oluşturulmuş koddan geldiği durumlarda meydana geldi. Daha fazla bilgi için sorun #43688 sayfasına bakın.

Julia 1.11'den itibaren, tüm tahsisatların bir türü bildirilmelidir.

Julia 1.8

Tahsisat profilcisi Julia 1.8'de eklendi.

source

Profile.Allocs içindeki yöntemler dışa aktarılmamıştır ve Profile.Allocs.fetch() gibi çağrılması gerekmektedir.

Profile.Allocs.printFunction
Profile.Allocs.print([io::IO = stdout,] [data::AllocResults = fetch()]; kwargs...)

Profiling sonuçlarını io'ya (varsayılan olarak, stdout) yazdırır. Eğer bir data vektörü sağlamazsanız, birikmiş geri izlerin içsel tamponu kullanılacaktır.

Geçerli anahtar kelime argümanlarının açıklaması için Profile.print'e bakın.

source
Profile.Allocs.fetchFunction
Profile.Allocs.fetch()

Kaydedilen tahsisatları alır ve bunları analiz edilebilecek Julia nesnelerine çözer.

source
Profile.Allocs.startFunction
Profile.Allocs.start(sample_rate::Gerçek)

Verilen örnek oranı ile tahsisatları kaydetmeye başlayın. 1.0'lık bir örnek oranı her şeyi kaydedecek; 0.0 hiçbir şeyi kaydetmeyecek.

source

Heap Snapshots

Profile.take_heap_snapshotFunction
Profile.take_heap_snapshot(filepath::String, all_one::Bool=false, streaming=false)
Profile.take_heap_snapshot(all_one::Bool=false; dir::String, streaming=false)

Yığın anlık görüntüsünü, Chrome Devtools Yığın Anlık Görüntüleyici tarafından beklenen JSON formatında (.heapsnapshot uzantısı) bir dosyaya ($pid_$timestamp.heapsnapshot) varsayılan olarak geçerli dizine (veya geçerli dizin yazılabilir değilse tempdir'e) yazın, veya verilen dir'e, veya verilen tam dosya yoluna, veya IO akışına.

Eğer all_one true ise, o zaman her nesnenin boyutunu bir olarak rapor edin, böylece kolayca sayılabilirler. Aksi takdirde, gerçek boyutu rapor edin.

Eğer streaming true ise, anlık görüntü verilerini dört dosyaya akıtarak, filepath'ı ön ek olarak kullanarak, tüm anlık görüntüyü bellekte tutmak zorunda kalmamak için bu seçeneği kullanacağız. Bu dosyalar daha sonra Profile.HeapSnapshot.assemble_snapshot() çağrılarak birleştirilebilir, bu işlem çevrimdışı yapılabilir.

NOT: Performans nedenleriyle streaming=true ayarını yapmanızı şiddetle tavsiye ederiz. Parçaları birleştirerek anlık görüntüyü yeniden oluşturmak, tüm anlık görüntüyü bellekte tutmayı gerektirir, bu nedenle anlık görüntü büyükse, işlenirken belleğiniz tükenebilir. Akış, anlık görüntüyü çevrimdışı olarak, iş yükünüz çalışmayı bitirdikten sonra yeniden oluşturmanıza olanak tanır. Eğer streaming=false (geriye dönük uyumluluk için varsayılan) ile bir anlık görüntü toplamaya çalışırsanız ve işleminiz sonlandırılırsa, bu her zaman sağladığınız dosya yoluyla aynı dizine parçaları kaydedecektir, böylece assemble_snapshot() aracılığıyla sonradan anlık görüntüyü yeniden oluşturabilirsiniz.

source

Profile içindeki yöntemler dışa aktarılmamıştır ve Profile.take_heap_snapshot() gibi çağrılmalıdır.

julia> using Profile

julia> Profile.take_heap_snapshot("snapshot.heapsnapshot")

Yığın üzerindeki julia nesnelerini izler ve kaydeder. Bu yalnızca Julia çöp toplayıcısı tarafından bilinen nesneleri kaydeder. Çöp toplayıcı tarafından yönetilmeyen dış kütüphaneler tarafından tahsis edilen bellek anlık görüntüde görünmeyecektir.

Yığın anlık görüntüsünü kaydederken OOM hatasından kaçınmak için, yığın anlık görüntüsünü dört dosyaya akıtarak akış seçeneği ekledik,

julia> using Profile

julia> Profile.take_heap_snapshot("snapshot"; streaming=true)

"snapshot" dosyası, oluşturulan dosyalar için ön ek olarak kullanılır.

Oluşturulan anlık görüntü dosyaları, aşağıdaki komutla çevrimdışı olarak birleştirilebilir:

julia> using Profile

julia> Profile.HeapSnapshot.assemble_snapshot("snapshot", "snapshot.heapsnapshot")

Oluşan yığın anlık görüntü dosyası, görüntülenmek üzere chrome geliştirici araçlarına yüklenebilir. Daha fazla bilgi için chrome devtools docs adresine bakın. Chromium yığın anlık görüntülerini analiz etmek için bir alternatif, VS Code uzantısı ms-vscode.vscode-js-profile-flamedir.

Firefox yığın anlık görüntüleri farklı bir formattadır ve Firefox şu anda Julia tarafından üretilen yığın anlık görüntülerini görüntülemek için kullanılamaz.