Mga kundisyon sa Go at ang kanilang mga kakaiba

Sa palagay mo ba ang dalawang opsyong ito para sa mga kundisyon ng pagsubok sa loob ng isang loop ay katumbas sa pagganap?

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


Nagsimula ang lahat sa isang "pag-init ng utak"; Kinailangan kong magbigay ng halimbawa ng pinakamainam na paghahanap para sa pinakamalaking even na numero sa hanay ng mga integer [-x....x]. Iniisip ko kung gaano kahusay ang magiging performance kung gumamit ako ng logical multiplication sa 1 para malaman kung ang isang numero ay pantay o hindi.


//Ρƒ Ρ‡Π΅Ρ‚Π½Ρ‹Ρ… чисСл послСдний Π±ΠΈΡ‚ всСгда Ρ€Π°Π²Π΅Π½ 0
value & 1 == 0
//vs классичСский ΠΌΠ΅Ρ‚ΠΎΠ΄
value % 2 == 0

Ang aking karanasan sa programming sa Go ay hindi masyadong malawak, higit sa isang taon at kalahati lamang, ginamit ko ito, bagaman madalas, ngunit para lamang sa mga layuning utilitarian (well, marahil maliban sa isang proyekto na may kaugnayan sa isang mataas na kargang serbisyo ng http), kaya ako nagsimula dito. Buksan ang GoLand at magsulat ng isang simpleng pagsubok


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
}

Nakakuha kami ng resulta na nagpapakita na kapag mas mataas ang threshold, mas madalas na lumilitaw ang mga pagbabago sa pagganap.

Ihambingmax 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

Malinaw na sa kasong ito, para sa iba't ibang mga threshold mayroon kaming iba't ibang mga hanay ng data ng pagsubok, ang pag-load ng processor (sa aking i5-2540M laptop) ay nag-iiba sa paligid ng 20..30%, ang memorya na inookupahan ng application na tumatakbo mula sa GoLand ay nasa average. tungkol sa 813MB - ito ay nakakaapekto rin sa pagiging maaasahan ng resulta, kailangan mong i-save ang mga kaso ng pagsubok sa disk at patakbuhin ang lahat ng mga pagsubok para sa bawat threshold sa paghihiwalay mula sa bawat isa.

At ngayon, iniisip kung paano ipatupad ang lahat ng ito nang may kaunting gastos, awtomatiko kong itinatama ang pagsusuri sa kondisyon

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

sa

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

Muli akong nagpapatakbo ng mga pagsusulit... at huminto ako sa pag-unawa sa anuman :)

Ang oras na ginugol sa pagpapatupad ay nagsisimulang mag-iba hindi na sa mga porsyento/fraction ng isang porsyento, ngunit sa pamamagitan ng 10..15%. Mabilis akong nagdagdag ng 2 pang pagsubok:

		
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
}

Pinapatakbo ko ito at nakuha ang larawang ito:paunang kapasidad ng array: 100000000

max na threshold: 128
resulta ng maxEvenDividing: 126 tagal 116.0066ms
resulta ng maxEvenDividing2: 126 na tagal 79.0045ms
resulta ng maxEvenConjunction: 126 na tagal 114.0065ms
resulta ng maxEvenConjunction2: 126 na tagal 83.0048ms

max na threshold: 256
resulta ng maxEvenDividing: 254 tagal 111.0063ms
resulta ng maxEvenDividing2: 254 na tagal 77.0044ms
resulta ng maxEvenConjunction: 254 na tagal 110.0063ms
resulta ng maxEvenConjunction2: 254 na tagal 80.0046ms

max na threshold: 512
resulta ng maxEvenDividing: 510 tagal 114.0066ms
resulta ng maxEvenDividing2: 510 na tagal 80.0045ms
resulta ng maxEvenConjunction: 510 na tagal 110.0063ms
resulta ng maxEvenConjunction2: 510 na tagal 80.0046ms

max na threshold: 1024
resulta ng maxEvenDividing: 1022 tagal 109.0063ms
resulta ng maxEvenDividing2: 1022 na tagal 77.0044ms
resulta ng maxEvenConjunction: 1022 na tagal 111.0063ms
resulta ng maxEvenConjunction2: 1022 na tagal 81.0047ms

max na threshold: 2048
resulta ng maxEvenDividing: 2046 tagal 114.0065ms
resulta ng maxEvenDividing2: 2046 na tagal 79.0045ms
resulta ng maxEvenConjunction: 2046 na tagal 113.0065ms
resulta ng maxEvenConjunction2: 2046 na tagal 81.0046ms

max na threshold: 4096
resulta ng maxEvenDividing: 4094 tagal 114.0065ms
resulta ng maxEvenDividing2: 4094 na tagal 80.0046ms
resulta ng maxEvenConjunction: 4094 na tagal 111.0063ms
resulta ng maxEvenConjunction2: 4094 na tagal 78.0045ms

max na threshold: 8192
resulta ng maxEvenDividing: 8190 tagal 107.0062ms
resulta ng maxEvenDividing2: 8190 na tagal 77.0044ms
resulta ng maxEvenConjunction: 8190 na tagal 111.0063ms
resulta ng maxEvenConjunction2: 8190 na tagal 77.0044ms

max na threshold: 16384
resulta ng maxEvenDividing: 16382 tagal 109.0063ms
resulta ng maxEvenDividing2: 16382 na tagal 77.0044ms
resulta ng maxEvenConjunction: 16382 na tagal 108.0062ms
resulta ng maxEvenConjunction2: 16382 na tagal 77.0044ms

max na threshold: 32768
resulta ng maxEvenDividing: 32766 tagal 112.0064ms
resulta ng maxEvenDividing2: 32766 na tagal 77.0044ms
resulta ng maxEvenConjunction: 32766 na tagal 109.0062ms
resulta ng maxEvenConjunction2: 32766 na tagal 78.0045ms

max na threshold: 65536
resulta ng maxEvenDividing: 65534 tagal 109.0062ms
resulta ng maxEvenDividing2: 65534 na tagal 75.0043ms
resulta ng maxEvenConjunction: 65534 na tagal 109.0063ms
resulta ng maxEvenConjunction2: 65534 na tagal 79.0045ms

max na threshold: 131072
resulta ng maxEvenDividing: 131070 tagal 108.0061ms
resulta ng maxEvenDividing2: 131070 na tagal 76.0044ms
resulta ng maxEvenConjunction: 131070 na tagal 110.0063ms
resulta ng maxEvenConjunction2: 131070 na tagal 80.0046ms

max na threshold: 262144
resulta ng maxEvenDividing: 262142 tagal 110.0063ms
resulta ng maxEvenDividing2: 262142 na tagal 76.0044ms
resulta ng maxEvenConjunction: 262142 na tagal 107.0061ms
resulta ng maxEvenConjunction2: 262142 na tagal 78.0044ms

max na threshold: 524288
resulta ng maxEvenDividing: 524286 tagal 109.0062ms
resulta ng maxEvenDividing2: 524286 na tagal 78.0045ms
resulta ng maxEvenConjunction: 524286 na tagal 109.0062ms
resulta ng maxEvenConjunction2: 524286 na tagal 80.0046ms

max na threshold: 1048576
resulta ng maxEvenDividing: 1048574 tagal 109.0063ms
resulta ng maxEvenDividing2: 1048574 na tagal 80.0045ms
resulta ng maxEvenConjunction: 1048574 na tagal 114.0066ms
resulta ng maxEvenConjunction2: 1048574 na tagal 78.0044ms

max na threshold: 2097152
resulta ng maxEvenDividing: 2097150 tagal 111.0064ms
resulta ng maxEvenDividing2: 2097150 na tagal 79.0045ms
resulta ng maxEvenConjunction: 2097150 na tagal 112.0064ms
resulta ng maxEvenConjunction2: 2097150 na tagal 77.0044ms

max na threshold: 4194304
resulta ng maxEvenDividing: 4194302 tagal 111.0063ms
resulta ng maxEvenDividing2: 4194302 na tagal 78.0045ms
resulta ng maxEvenConjunction: 4194302 na tagal 111.0063ms
resulta ng maxEvenConjunction2: 4194302 na tagal 77.0044ms

max na threshold: 8388608
resulta ng maxEvenDividing: 8388606 tagal 109.0062ms
resulta ng maxEvenDividing2: 8388606 na tagal 78.0045ms
resulta ng maxEvenConjunction: 8388606 na tagal 114.0065ms
resulta ng maxEvenConjunction2: 8388606 na tagal 78.0045ms

max na threshold: 16777216
resulta ng maxEvenDividing: 16777214 tagal 109.0062ms
resulta ng maxEvenDividing2: 16777214 na tagal 77.0044ms
resulta ng maxEvenConjunction: 16777214 na tagal 109.0063ms
resulta ng maxEvenConjunction2: 16777214 na tagal 77.0044ms

max na threshold: 33554432
resulta ng maxEvenDividing: 33554430 tagal 113.0065ms
resulta ng maxEvenDividing2: 33554430 na tagal 78.0045ms
resulta ng maxEvenConjunction: 33554430 na tagal 110.0063ms
resulta ng maxEvenConjunction2: 33554430 na tagal 80.0045ms

max na threshold: 67108864
resulta ng maxEvenDividing: 67108860 tagal 112.0064ms
resulta ng maxEvenDividing2: 67108860 na tagal 77.0044ms
resulta ng maxEvenConjunction: 67108860 na tagal 112.0064ms
resulta ng maxEvenConjunction2: 67108860 na tagal 80.0046ms

max na threshold: 134217728
resulta ng maxEvenDividing: 134217726 tagal 109.0063ms
resulta ng maxEvenDividing2: 134217726 na tagal 78.0044ms
resulta ng maxEvenConjunction: 134217726 na tagal 114.0065ms
resulta ng maxEvenConjunction2: 134217726 na tagal 81.0047ms

max na threshold: 268435456
resulta ng maxEvenDividing: 268435446 tagal 111.0064ms
resulta ng maxEvenDividing2: 268435446 na tagal 79.0045ms
resulta ng maxEvenConjunction: 268435446 na tagal 114.0065ms
resulta ng maxEvenConjunction2: 268435446 na tagal 79.0045ms

max na threshold: 536870912
resulta ng maxEvenDividing: 536870910 tagal 107.0062ms
resulta ng maxEvenDividing2: 536870910 na tagal 76.0043ms
resulta ng maxEvenConjunction: 536870910 na tagal 109.0062ms
resulta ng maxEvenConjunction2: 536870910 na tagal 80.0046ms

Hindi ako makakita ng malinaw na paliwanag kung bakit hindi ino-optimize ng Go compiler ang code at palaging sinusuri ang pangalawang kundisyon, kahit na mali ang una. O baka naman malabo lang ang mata ko at wala akong nakikitang mali? O kailangan mo bang magbigay ng ilang mga espesyal na tagubilin sa compiler? Matutuwa ako sa mga matinong komento.

PS: Oo, para lamang sa kasiyahan, nagpatakbo ako ng mga katulad na pagsubok sa Java 5 at Java 7/8 - lahat ay malinaw, ang oras ng pagpapatupad ay pareho.

Pinagmulan: www.habr.com

Magdagdag ng komento