Apakah menurut Anda kedua opsi untuk kondisi pengujian di dalam loop ini memiliki kinerja yang setara?
if a > b && c*2 > d {
....
}
// ΠΈ
if a <= b {
continue;
}
if c*2 > d {
....
}
Semuanya dimulai dengan βpemanasan otakβ; Saya harus memberikan contoh pencarian optimal untuk bilangan genap terbesar dalam array bilangan bulat [-x....x]. Saya bertanya-tanya seberapa baik kinerjanya jika saya menggunakan perkalian logika dengan 1 untuk mengetahui apakah suatu bilangan genap atau tidak.
//Ρ ΡΠ΅ΡΠ½ΡΡ
ΡΠΈΡΠ΅Π» ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠΉ Π±ΠΈΡ Π²ΡΠ΅Π³Π΄Π° ΡΠ°Π²Π΅Π½ 0
value & 1 == 0
//vs ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΌΠ΅ΡΠΎΠ΄
value % 2 == 0
Pengalaman pemrograman saya di Go tidak terlalu luas, hanya lebih dari satu setengah tahun, saya menggunakannya, meskipun sering, tetapi murni untuk tujuan utilitarian (yah, mungkin kecuali untuk satu proyek yang terkait dengan layanan http beban tinggi), jadi saya dimulai dengan itu. Buka GoLand dan tulis tes sederhana
package main
import (
"fmt"
"log"
"math"
"math/rand"
"time"
)
const size = 100000000 //math.MaxInt32*2
type Result struct {
Name string
Duration time.Duration
Value int32
}
func main() {
log.Println("initial array capacity: " + fmt.Sprint(size))
var maxValue int32
// ΠΡΠ΄Π΅ΠΌ Π²Π°ΡΡΠΈΡΠΎΠ²Π°ΡΡ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½ ΡΠΈΡΠ΅Π» ΠΎΡ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ³ΠΎ
// Π΄ΠΎ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ³ΠΎ. Π§Π΅ΠΌ ΠΌΠ΅Π½ΡΡΠ΅ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½, ΡΠ΅ΠΌ Π±ΠΎΠ»ΡΡΠ΅
// ΠΏΡΠΎΡΠ΅ΡΡΠΎΡΠ½ΠΎΠ³ΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Π±ΡΠ΄Π΅Ρ ΡΡ
ΠΎΠ΄ΠΈΡΡ Π½Π° ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ
// ΡΡΠ°Π²Π½Π΅Π½ΠΈΡ ΡΠ΅ΠΊΡΡΠ΅Π³ΠΎ ΡΠΈΡΠ»Π°, Ρ ΡΠ°Π½Π΅Π΅ Π½Π°ΠΉΠ΄Π΅Π½Π½ΡΠΌ ΠΈ Π½Π°ΠΎΠ±ΠΎΡΠΎΡ
for maxValue = 128; maxValue < math.MaxInt32/2+1; maxValue = maxValue * 2 {
test(maxValue)
}
}
func test(maxValue int32) {
log.Println("max threshold: " + fmt.Sprint(maxValue))
arr := make([]int32, size)
for i := range arr {
arr[i] = rand.Int31n(maxValue)
// Π² ΡΠ΅ΡΡΠΎΠ²ΡΡ
Π΄Π°Π½Π½ΡΡ
Π½Π°ΠΌ Π½ΡΠΆΠ½Ρ ΠΈ ΠΎΡΡΠΈΡΠ°ΡΠ΅Π»ΡΠ½ΡΠ΅ ΡΠΈΡΠ»Π°
sign := rand.Intn(2)
if sign == 1 {
arr[i] = -arr[i]
}
}
// Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΡΠ΅ΡΡ "Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ ΠΎΡΡΠ°ΡΠΊΠΎΠΌ"
result := maxEvenDividing("maxEvenDividing", arr)
log.Printf(result.Name+"t result: "+fmt.Sprint(result.Value)+"ttduration %s", result.Duration)
// Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΡΠ΅ΡΡ "ΠΊΠΎΠ½ΡΡΠ½ΠΊΡΠΈΠΈ"
result = maxEvenConjunction("maxEvenConjunction", arr)
log.Printf(result.Name+"t result: "+fmt.Sprint(result.Value)+"ttduration %s", result.Duration)
}
func maxEvenDividing(name string, arr []int32) Result {
start := time.Now()
var current int32 = math.MinInt32
for _, value := range arr {
if value > current && value%2 == 0 {
current = value
}
}
duration := time.Since(start)
result := Result{name, duration, current}
return result
}
func maxEvenConjunction(name string, arr []int32) Result {
start := time.Now()
var current int32 = math.MinInt32
for _, value := range arr {
if value > current && value&1 == 0 {
current = value
}
}
duration := time.Since(start)
result := Result{name, duration, current}
return result
}
Kami mendapatkan hasil yang menunjukkan bahwa semakin tinggi ambang batas, semakin sering muncul fluktuasi kinerja.
Bandingkanmax threshold: 128
maxEvenDividing result: 126 duration 116.0067ms
maxEvenConjunction result: 126 duration 116.0066ms
max threshold: 16384
maxEvenDividing result: 16382 duration 115.0066ms
maxEvenConjunction result: 16382 duration 111.0064ms
......
max threshold: 8388608
maxEvenDividing result: 8388606 duration 109.0063ms
maxEvenConjunction result: 8388606 duration 109.0062ms
max threshold: 16777216
maxEvenDividing result: 16777214 duration 108.0062ms
maxEvenConjunction result: 16777214 duration 109.0062ms
max threshold: 33554432
maxEvenDividing result: 33554430 duration 114.0066ms
maxEvenConjunction result: 33554430 duration 110.0063ms
max threshold: 67108864
maxEvenDividing result: 67108860 duration 111.0064ms
maxEvenConjunction result: 67108860 duration 109.0062ms
max threshold: 134217728
maxEvenDividing result: 134217726 duration 108.0062ms
maxEvenConjunction result: 134217726 duration 109.0063ms
max threshold: 268435456
maxEvenDividing result: 268435446 duration 111.0063ms
maxEvenConjunction result: 268435446 duration 110.0063ms
Jelas bahwa dalam hal ini, untuk ambang batas yang berbeda kami memiliki kumpulan data pengujian yang berbeda, beban prosesor (pada laptop i5-2540M saya) bervariasi sekitar 20..30%, memori yang ditempati oleh aplikasi yang dijalankan dari GoLand rata-rata sekitar 813MB - ini juga mempengaruhi keandalan hasil, Anda perlu menyimpan kasus pengujian pada disk dan menjalankan semua pengujian untuk setiap ambang batas secara terpisah satu sama lain.
Dan sekarang, memikirkan bagaimana menerapkan semua ini dengan biaya minimal, saya secara otomatis memperbaiki pemeriksaan kondisi
if value > current && value&1 == 0 {
current = value
}
pada
if value <= current {
continue;
}
if value&1 == 0 {
current = value
}
Saya menjalankan tes lagi... dan saya berhenti memahami apa pun :)
Waktu yang dihabiskan untuk eksekusi mulai berbeda tidak lagi berdasarkan persentase/pecahan persen, tetapi sebesar 10..15%.Saya segera menambahkan 2 tes lagi:
func maxEvenDividing2(name string, arr []int32) Result {
start := time.Now()
var current int32 = math.MinInt32
for _, value := range arr {
if value <= current {
continue
}
if value%2 == 0 {
current = value
}
}
duration := time.Since(start)
result := Result{name, duration, current}
return result
}
func maxEvenConjunction2(name string, arr []int32) Result {
start := time.Now()
var current int32 = math.MinInt32
for _, value := range arr {
if value <= current {
continue
}
if value&1 == 0 {
current = value
}
}
duration := time.Since(start)
result := Result{name, duration, current}
return result
}
Saya menjalankannya dan mendapatkan gambar ini:kapasitas array awal: 100000000
ambang batas maksimal: 128
hasil maxEvenDividing: 126 durasi 116.0066ms
hasil maxEvenDividing2: 126 durasi 79.0045ms
hasil maxEvenConjunction: 126 durasi 114.0065ms
hasil maxEvenConjunction2: 126 durasi 83.0048ms
ambang batas maksimal: 256
hasil maxEvenDividing: 254 durasi 111.0063ms
hasil maxEvenDividing2: 254 durasi 77.0044ms
hasil maxEvenConjunction: 254 durasi 110.0063ms
hasil maxEvenConjunction2: 254 durasi 80.0046ms
ambang batas maksimal: 512
hasil maxEvenDividing: 510 durasi 114.0066ms
hasil maxEvenDividing2: 510 durasi 80.0045ms
hasil maxEvenConjunction: 510 durasi 110.0063ms
hasil maxEvenConjunction2: 510 durasi 80.0046ms
ambang batas maksimal: 1024
hasil maxEvenDividing: 1022 durasi 109.0063ms
hasil maxEvenDividing2: 1022 durasi 77.0044ms
hasil maxEvenConjunction: 1022 durasi 111.0063ms
hasil maxEvenConjunction2: 1022 durasi 81.0047ms
ambang batas maksimal: 2048
hasil maxEvenDividing: 2046 durasi 114.0065ms
hasil maxEvenDividing2: 2046 durasi 79.0045ms
hasil maxEvenConjunction: 2046 durasi 113.0065ms
hasil maxEvenConjunction2: 2046 durasi 81.0046ms
ambang batas maksimal: 4096
hasil maxEvenDividing: 4094 durasi 114.0065ms
hasil maxEvenDividing2: 4094 durasi 80.0046ms
hasil maxEvenConjunction: 4094 durasi 111.0063ms
hasil maxEvenConjunction2: 4094 durasi 78.0045ms
ambang batas maksimal: 8192
hasil maxEvenDividing: 8190 durasi 107.0062ms
hasil maxEvenDividing2: 8190 durasi 77.0044ms
hasil maxEvenConjunction: 8190 durasi 111.0063ms
hasil maxEvenConjunction2: 8190 durasi 77.0044ms
ambang batas maksimal: 16384
hasil maxEvenDividing: 16382 durasi 109.0063ms
hasil maxEvenDividing2: 16382 durasi 77.0044ms
hasil maxEvenConjunction: 16382 durasi 108.0062ms
hasil maxEvenConjunction2: 16382 durasi 77.0044ms
ambang batas maksimal: 32768
hasil maxEvenDividing: 32766 durasi 112.0064ms
hasil maxEvenDividing2: 32766 durasi 77.0044ms
hasil maxEvenConjunction: 32766 durasi 109.0062ms
hasil maxEvenConjunction2: 32766 durasi 78.0045ms
ambang batas maksimal: 65536
hasil maxEvenDividing: 65534 durasi 109.0062ms
hasil maxEvenDividing2: 65534 durasi 75.0043ms
hasil maxEvenConjunction: 65534 durasi 109.0063ms
hasil maxEvenConjunction2: 65534 durasi 79.0045ms
ambang batas maksimal: 131072
hasil maxEvenDividing: 131070 durasi 108.0061ms
hasil maxEvenDividing2: 131070 durasi 76.0044ms
hasil maxEvenConjunction: 131070 durasi 110.0063ms
hasil maxEvenConjunction2: 131070 durasi 80.0046ms
ambang batas maksimal: 262144
hasil maxEvenDividing: 262142 durasi 110.0063ms
hasil maxEvenDividing2: 262142 durasi 76.0044ms
hasil maxEvenConjunction: 262142 durasi 107.0061ms
hasil maxEvenConjunction2: 262142 durasi 78.0044ms
ambang batas maksimal: 524288
hasil maxEvenDividing: 524286 durasi 109.0062ms
hasil maxEvenDividing2: 524286 durasi 78.0045ms
hasil maxEvenConjunction: 524286 durasi 109.0062ms
hasil maxEvenConjunction2: 524286 durasi 80.0046ms
ambang batas maksimal: 1048576
hasil maxEvenDividing: 1048574 durasi 109.0063ms
hasil maxEvenDividing2: 1048574 durasi 80.0045ms
hasil maxEvenConjunction: 1048574 durasi 114.0066ms
hasil maxEvenConjunction2: 1048574 durasi 78.0044ms
ambang batas maksimal: 2097152
hasil maxEvenDividing: 2097150 durasi 111.0064ms
hasil maxEvenDividing2: 2097150 durasi 79.0045ms
hasil maxEvenConjunction: 2097150 durasi 112.0064ms
hasil maxEvenConjunction2: 2097150 durasi 77.0044ms
ambang batas maksimal: 4194304
hasil maxEvenDividing: 4194302 durasi 111.0063ms
hasil maxEvenDividing2: 4194302 durasi 78.0045ms
hasil maxEvenConjunction: 4194302 durasi 111.0063ms
hasil maxEvenConjunction2: 4194302 durasi 77.0044ms
ambang batas maksimal: 8388608
hasil maxEvenDividing: 8388606 durasi 109.0062ms
hasil maxEvenDividing2: 8388606 durasi 78.0045ms
hasil maxEvenConjunction: 8388606 durasi 114.0065ms
hasil maxEvenConjunction2: 8388606 durasi 78.0045ms
ambang batas maksimal: 16777216
hasil maxEvenDividing: 16777214 durasi 109.0062ms
hasil maxEvenDividing2: 16777214 durasi 77.0044ms
hasil maxEvenConjunction: 16777214 durasi 109.0063ms
hasil maxEvenConjunction2: 16777214 durasi 77.0044ms
ambang batas maksimal: 33554432
hasil maxEvenDividing: 33554430 durasi 113.0065ms
hasil maxEvenDividing2: 33554430 durasi 78.0045ms
hasil maxEvenConjunction: 33554430 durasi 110.0063ms
hasil maxEvenConjunction2: 33554430 durasi 80.0045ms
ambang batas maksimal: 67108864
hasil maxEvenDividing: 67108860 durasi 112.0064ms
hasil maxEvenDividing2: 67108860 durasi 77.0044ms
hasil maxEvenConjunction: 67108860 durasi 112.0064ms
hasil maxEvenConjunction2: 67108860 durasi 80.0046ms
ambang batas maksimal: 134217728
hasil maxEvenDividing: 134217726 durasi 109.0063ms
hasil maxEvenDividing2: 134217726 durasi 78.0044ms
hasil maxEvenConjunction: 134217726 durasi 114.0065ms
hasil maxEvenConjunction2: 134217726 durasi 81.0047ms
ambang batas maksimal: 268435456
hasil maxEvenDividing: 268435446 durasi 111.0064ms
hasil maxEvenDividing2: 268435446 durasi 79.0045ms
hasil maxEvenConjunction: 268435446 durasi 114.0065ms
hasil maxEvenConjunction2: 268435446 durasi 79.0045ms
ambang batas maksimal: 536870912
hasil maxEvenDividing: 536870910 durasi 107.0062ms
hasil maxEvenDividing2: 536870910 durasi 76.0043ms
hasil maxEvenConjunction: 536870910 durasi 109.0062ms
hasil maxEvenConjunction2: 536870910 durasi 80.0046ms
Saya tidak dapat menemukan penjelasan yang jelas mengapa kompiler Go tidak mengoptimalkan kode dan selalu memeriksa kondisi kedua, meskipun kondisi pertama salah. Atau mungkin mataku hanya buram dan tidak melihat kesalahan yang jelas? Atau apakah Anda perlu memberikan beberapa instruksi khusus kepada kompiler? Saya akan senang untuk komentar yang masuk akal.
PS: Ya, hanya untuk bersenang-senang, saya menjalankan tes serupa di Java 5 dan Java 7/8 - semuanya jelas, waktu eksekusinya sama.
Sumber: www.habr.com