Penanda aras dengan Golang

WBOY
Lepaskan: 2024-09-05 21:31:03
asal
845 orang telah melayarinya

Hello Gophers ?

Dalam catatan blog ini, saya akan menunjukkan kepada anda cara menggunakan alat hebat yang terbina dalam pakej ujian #golang. Bagaimanakah anda akan menguji prestasi sekeping kod atau fungsi? Gunakan ujian penanda aras.

Jom.

Untuk ujian ini, saya akan menggunakan Nombor Fibonacci klasik atau Jujukan Fibonacci, yang ditentukan oleh:

if (x < 2) 
   F(0) = 1
   F(2) = 2
else 
   F(x) = F(x-1) + F(x-2)

In practice, the sequence is:
1, 1, 2, 3, 5, 8, 13, etc.
Salin selepas log masuk

Jujukan ini penting kerana ia muncul dalam beberapa bahagian matematik dan alam semula jadi, seperti yang ditunjukkan di bawah:

Benchmark with Golang

Terdapat beberapa cara untuk melaksanakan kod ini dan saya akan memilih dua untuk ujian penanda aras kami: kaedah rekursif dan berulang untuk mengiranya. Objektif utama fungsi adalah untuk menyediakan kedudukan dan mengembalikan nombor Fibonacci pada kedudukan itu.

Kaedah Rekursif

// main.go

func fibRecursive(n int) int {
    if n <= 2 {
        return 1
    }
    return fibRecursive(n-1) + fibRecursive(n-2)
}
Salin selepas log masuk

Kaedah Berulang

// main.go

func fibIterative(position uint) uint {
    slc := make([]uint, position)
    slc[0] = 1
    slc[1] = 1

    if position <= 2 {
        return 1
    }

    var result, i uint
    for i = 2; i < position; i++ {
        result = slc[i-1] + slc[i-2]
        slc[i] = result
    }

    return result
}
Salin selepas log masuk

Kaedah ini tidak dioptimumkan, tetapi keputusan ujian adalah berbeza dengan ketara walaupun untuk bilangan yang kecil. Anda akan melihat ini dalam ujian. Untuk mengikuti kod tersebut, anda boleh klik di sini.

Sekarang, untuk ujian penanda aras, mari tulis beberapa ujian dalam fail _main_test.go. Menggunakan dokumentasi Golang pada penanda aras, anda boleh mencipta fungsi untuk diuji seperti berikut:

// main_test.go

// The key is to start every function you want to benchmark with the keyword Benchmark and use b *testing.B instead of t *testing.T as input 
func BenchmarkFibIterative(b *testing.B) {
    // Use this for-loop to ensure the code will behave correctly. 
    // Now, you can put the function or piece of code you want to test
    for i := 0; i < b.N; i++ { 
        fibIterative(uint(100))
    }
}

// Same as above
func BenchmarkFibRecursive(b *testing.B) {
    for i := 0; i < b.N; i++ {
        fibRecursive(100)
    }
}
Salin selepas log masuk

Soalan, sebelum anda meneruskan: yang manakah lebih cepat?

Mari kita jalankan ujian untuk nombor yang kecil (10) dan untuk nombor yang lebih besar sedikit (80). Untuk menjalankan ujian penanda aras, anda hanya jalankan arahan:

pergi ujian -bench=NameoftheFunction

Jika anda ingin mengetahui lebih lanjut tentang arahan ini, semak di sini.

Ujian pertama: kedudukan=10

//(fibIterative)
Results:
cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
BenchmarkFibIterative-8         24491042                42.50 ns/op
PASS
ok      playground      1.651s
Salin selepas log masuk

Mari kita analisis dengan bantuan imej ini:

Benchmark with Golang

Menurut imej, kami mempunyai 8 teras untuk ujian, tiada had masa (ia akan berjalan sehingga selesai). Ia mengambil masa 1.651s untuk menyelesaikan tugasan itu.

==== Extra ====
We got 24,491,042 iterations (computations), and each iteration (op) took 42.50 ns.

Doing some math, we can calculate how much time one op took:

42.50 ns/op with 1 ns = 1/1,000,000,000 s
op ≈ 2.35270590588e-12 s
==== Extra ====
Salin selepas log masuk

Itu keputusan yang baik. Mari semak fungsi rekursif untuk kedudukan 10:

// Results
BenchmarkFibRecursive-8          6035011               187.8 ns/op
PASS
ok      playground      1.882s
Salin selepas log masuk

Kita dapat lihat bahawa ia mengambil masa 1.882s untuk menyelesaikan tugas itu.

Fungsi berulang dimenangi beberapa saat. Mari cuba satu lagi ujian dengan:

Kedudukan 50

// Results for the Iterative Function

cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
BenchmarkFibIterative-8         27896118                45.37 ns/op
PASS
ok      playground      2.876s

// Results for the Recursive Function

cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
BenchmarkFibRecursive-8          6365198               186.3 ns/op
PASS
ok      playground      1.918s
Salin selepas log masuk

Wah! Kini fungsi rekursif lebih pantas?

Mari kita selesaikan dengan nombor yang lebih besar sedikit.

Kedudukan 80

// Results for the Iterative Function

cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
BenchmarkFibIterative-8          5102344               229.5 ns/op
PASS
ok      playground      1.933s

// Results for the Recursive Function
// My poor PC couldn’t handle it, so I had to reduce the position to 50 just to get some results printed.

cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
BenchmarkFibRecursive-8                1        44319299474 ns/op
PASS
ok      playground      44.951s
Salin selepas log masuk

Perbezaan sangat besar. Untuk kedudukan 80, pendekatan berulang mengambil masa kira-kira 2 saat. Untuk kedudukan 50, fungsi rekursif mengambil masa sekitar 45 saat. Ini menunjukkan kepentingan menanda aras kod anda apabila projek Golang anda mula perlahan.

Kesimpulan

Jika kod pengeluaran anda berjalan perlahan atau lebih perlahan tanpa diduga, anda boleh menggunakan teknik ini, digabungkan dengan pprof atau alatan lain daripada pakej ujian terbina dalam, untuk mengenal pasti dan menguji prestasi kod anda kurang baik dan cara mengoptimumkannya.

Nota sampingan: tidak semua kod yang cantik di mata adalah lebih berprestasi.

Senaman Tambahan

Bolehkah anda mencari cara yang lebih baik untuk meningkatkan fungsi rekursif? (Petua: gunakan Pengaturcaraan Dinamik). Artikel ini menerangkan sebab untuk beberapa nombor kecil, strategi rekursif adalah lebih baik.

Atas ialah kandungan terperinci Penanda aras dengan Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!