Kaayaan di Go jeung quirks maranéhna

Naha anjeun pikir dua pilihan ieu pikeun nguji kaayaan di jero loop sami sareng kinerja?

		
if a > b && c*2 > d {
	....
}
// и
if a <= b  { 
  continue;
}
if c*2 > d {
 ....
}


Éta sadayana dimimitian ku "panas-panas otak"; Kuring kedah masihan conto milarian optimal pikeun nomer genap panggedéna dina sajumlah integer [-x....x]. Kuring wondering sabaraha kinerja hadé bakal jadi lamun kuring dipaké multiplication logis ku 1 pikeun angka kaluar naha angka hiji malah atanapi henteu.


//у четных чисел последний бит всегда равен 0
value & 1 == 0
//vs классический метод
value % 2 == 0

Pangalaman programming abdi di Go teu pisan éksténsif, ngan leuwih sataun satengah, abdi dipaké, sanajan mindeng, tapi murni pikeun tujuan utilitarian (ogé, meureun iwal hiji proyék nu patali jeung layanan http beban tinggi), jadi kuring dimimitian ku eta. Buka GoLand sareng tulis tés saderhana


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 nampi hasil anu nunjukkeun yén langkung luhur ambangna, langkung sering turun naek dina pagelaran muncul.

Bandingkeunmax 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

Éta jelas yén dina hal ieu, pikeun ambang anu béda kami gaduh set data tés anu béda, beban prosesor (dina laptop i5-2540M kuring) beda-beda sakitar 20..30%, mémori anu dijajah ku aplikasi anu ngajalankeun ti GoLand rata-rata. kira-kira 813MB - ieu ogé mangaruhan reliabiliti hasilna, Anjeun kudu nyimpen kasus test dina disk jeung ngajalankeun sagala tés pikeun tiap bangbarung di isolasi ti silih.

Sareng ayeuna, pamikiran ngeunaan kumaha nerapkeun sadayana ieu kalayan biaya minimal, kuring otomatis ngabenerkeun cek kaayaan

		
if value > current && value&1 == 0 {
	current = value
}

dina

		
if value <= current {
        continue;
}
if value&1 == 0 {
	current = value
}

Kuring ngajalankeun tés deui ... sareng kuring eureun ngartos naon waé :)

waktos spent dina palaksanaan mimiti béda teu ku percentages / fraksi persen, tapi ku 10..15%.Kuring gancang nambahkeun 2 tés deui:

		
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
}

Kuring ngajalankeun éta sareng kéngingkeun gambar ieu:kapasitas Asép Sunandar Sunarya awal: 100000000

bangbarung max: 128
maxEvenDividing hasilna: 126 durasi 116.0066ms
maxEvenDividing2 hasilna: 126 durasi 79.0045ms
hasil maxEvenConjunction: 126 durasi 114.0065ms
maxEvenConjunction2 hasilna: 126 durasi 83.0048ms

bangbarung max: 256
maxEvenDividing hasilna: 254 durasi 111.0063ms
maxEvenDividing2 hasilna: 254 durasi 77.0044ms
hasil maxEvenConjunction: 254 durasi 110.0063ms
maxEvenConjunction2 hasilna: 254 durasi 80.0046ms

bangbarung max: 512
maxEvenDividing hasilna: 510 durasi 114.0066ms
maxEvenDividing2 hasilna: 510 durasi 80.0045ms
hasil maxEvenConjunction: 510 durasi 110.0063ms
maxEvenConjunction2 hasilna: 510 durasi 80.0046ms

bangbarung max: 1024
maxEvenDividing hasilna: 1022 durasi 109.0063ms
maxEvenDividing2 hasilna: 1022 durasi 77.0044ms
hasil maxEvenConjunction: 1022 durasi 111.0063ms
maxEvenConjunction2 hasilna: 1022 durasi 81.0047ms

bangbarung max: 2048
maxEvenDividing hasilna: 2046 durasi 114.0065ms
maxEvenDividing2 hasilna: 2046 durasi 79.0045ms
hasil maxEvenConjunction: 2046 durasi 113.0065ms
maxEvenConjunction2 hasilna: 2046 durasi 81.0046ms

bangbarung max: 4096
maxEvenDividing hasilna: 4094 durasi 114.0065ms
maxEvenDividing2 hasilna: 4094 durasi 80.0046ms
hasil maxEvenConjunction: 4094 durasi 111.0063ms
maxEvenConjunction2 hasilna: 4094 durasi 78.0045ms

bangbarung max: 8192
maxEvenDividing hasilna: 8190 durasi 107.0062ms
maxEvenDividing2 hasilna: 8190 durasi 77.0044ms
hasil maxEvenConjunction: 8190 durasi 111.0063ms
maxEvenConjunction2 hasilna: 8190 durasi 77.0044ms

bangbarung max: 16384
maxEvenDividing hasilna: 16382 durasi 109.0063ms
maxEvenDividing2 hasilna: 16382 durasi 77.0044ms
hasil maxEvenConjunction: 16382 durasi 108.0062ms
maxEvenConjunction2 hasilna: 16382 durasi 77.0044ms

bangbarung max: 32768
maxEvenDividing hasilna: 32766 durasi 112.0064ms
maxEvenDividing2 hasilna: 32766 durasi 77.0044ms
hasil maxEvenConjunction: 32766 durasi 109.0062ms
maxEvenConjunction2 hasilna: 32766 durasi 78.0045ms

bangbarung max: 65536
maxEvenDividing hasilna: 65534 durasi 109.0062ms
maxEvenDividing2 hasilna: 65534 durasi 75.0043ms
hasil maxEvenConjunction: 65534 durasi 109.0063ms
maxEvenConjunction2 hasilna: 65534 durasi 79.0045ms

bangbarung max: 131072
maxEvenDividing hasilna: 131070 durasi 108.0061ms
maxEvenDividing2 hasilna: 131070 durasi 76.0044ms
hasil maxEvenConjunction: 131070 durasi 110.0063ms
maxEvenConjunction2 hasilna: 131070 durasi 80.0046ms

bangbarung max: 262144
maxEvenDividing hasilna: 262142 durasi 110.0063ms
maxEvenDividing2 hasilna: 262142 durasi 76.0044ms
hasil maxEvenConjunction: 262142 durasi 107.0061ms
maxEvenConjunction2 hasilna: 262142 durasi 78.0044ms

bangbarung max: 524288
maxEvenDividing hasilna: 524286 durasi 109.0062ms
maxEvenDividing2 hasilna: 524286 durasi 78.0045ms
hasil maxEvenConjunction: 524286 durasi 109.0062ms
maxEvenConjunction2 hasilna: 524286 durasi 80.0046ms

bangbarung max: 1048576
maxEvenDividing hasilna: 1048574 durasi 109.0063ms
maxEvenDividing2 hasilna: 1048574 durasi 80.0045ms
hasil maxEvenConjunction: 1048574 durasi 114.0066ms
maxEvenConjunction2 hasilna: 1048574 durasi 78.0044ms

bangbarung max: 2097152
maxEvenDividing hasilna: 2097150 durasi 111.0064ms
maxEvenDividing2 hasilna: 2097150 durasi 79.0045ms
hasil maxEvenConjunction: 2097150 durasi 112.0064ms
maxEvenConjunction2 hasilna: 2097150 durasi 77.0044ms

bangbarung max: 4194304
maxEvenDividing hasilna: 4194302 durasi 111.0063ms
maxEvenDividing2 hasilna: 4194302 durasi 78.0045ms
hasil maxEvenConjunction: 4194302 durasi 111.0063ms
maxEvenConjunction2 hasilna: 4194302 durasi 77.0044ms

bangbarung max: 8388608
maxEvenDividing hasilna: 8388606 durasi 109.0062ms
maxEvenDividing2 hasilna: 8388606 durasi 78.0045ms
hasil maxEvenConjunction: 8388606 durasi 114.0065ms
maxEvenConjunction2 hasilna: 8388606 durasi 78.0045ms

bangbarung max: 16777216
maxEvenDividing hasilna: 16777214 durasi 109.0062ms
maxEvenDividing2 hasilna: 16777214 durasi 77.0044ms
hasil maxEvenConjunction: 16777214 durasi 109.0063ms
maxEvenConjunction2 hasilna: 16777214 durasi 77.0044ms

bangbarung max: 33554432
maxEvenDividing hasilna: 33554430 durasi 113.0065ms
maxEvenDividing2 hasilna: 33554430 durasi 78.0045ms
hasil maxEvenConjunction: 33554430 durasi 110.0063ms
maxEvenConjunction2 hasilna: 33554430 durasi 80.0045ms

bangbarung max: 67108864
maxEvenDividing hasilna: 67108860 durasi 112.0064ms
maxEvenDividing2 hasilna: 67108860 durasi 77.0044ms
hasil maxEvenConjunction: 67108860 durasi 112.0064ms
maxEvenConjunction2 hasilna: 67108860 durasi 80.0046ms

bangbarung max: 134217728
maxEvenDividing hasilna: 134217726 durasi 109.0063ms
maxEvenDividing2 hasilna: 134217726 durasi 78.0044ms
hasil maxEvenConjunction: 134217726 durasi 114.0065ms
maxEvenConjunction2 hasilna: 134217726 durasi 81.0047ms

bangbarung max: 268435456
maxEvenDividing hasilna: 268435446 durasi 111.0064ms
maxEvenDividing2 hasilna: 268435446 durasi 79.0045ms
hasil maxEvenConjunction: 268435446 durasi 114.0065ms
maxEvenConjunction2 hasilna: 268435446 durasi 79.0045ms

bangbarung max: 536870912
maxEvenDividing hasilna: 536870910 durasi 107.0062ms
maxEvenDividing2 hasilna: 536870910 durasi 76.0043ms
hasil maxEvenConjunction: 536870910 durasi 109.0062ms
maxEvenConjunction2 hasilna: 536870910 durasi 80.0046ms

Abdi henteu tiasa mendakan panjelasan anu jelas naha kompiler Go henteu ngaoptimalkeun kode sareng mariksa kaayaan kadua, sanaos anu kahiji palsu. Atawa meureun panon kuring ngan kabur sarta kuring teu ningali kasalahan atra? Atawa anjeun kudu nyadiakeun sababaraha parentah husus pikeun compiler nu? Abdi bakal bungah pikeun komentar wijaksana.

PS: Leres, ngan pikeun senang, kuring ngajalankeun tés anu sami dina Java 5 sareng Java 7/8 - sadayana jelas, waktos palaksanaan sami.

sumber: www.habr.com

Tambahkeun komentar