Apstākļi Go un to dīvainības

Vai, jÅ«suprāt, Ŕīs divas iespējas cilpas apstākļu testÄ“Å”anai ir lÄ«dzvērtÄ«gas veiktspējai?

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


Viss sākās ar ā€œsmadzeņu iesildÄ«Å”anuā€; man bija jāsniedz piemērs optimālai lielākā pāra skaitļa meklÄ“Å”anai veselu skaitļu masÄ«vā [-x....x]. Es domāju, cik daudz labāka veiktspēja bÅ«tu, ja es izmantotu loÄ£isko reizināŔanu ar 1, lai noskaidrotu, vai skaitlis ir pāra vai nē.


//у чŠµŃ‚Š½Ń‹Ń… чŠøсŠµŠ» ŠæŠ¾ŃŠ»ŠµŠ“Š½ŠøŠ¹ Š±Šøт Š²ŃŠµŠ³Š“Š° рŠ°Š²ŠµŠ½ 0
value & 1 == 0
//vs ŠŗŠ»Š°ŃŃŠøчŠµŃŠŗŠøŠ¹ Š¼ŠµŃ‚Š¾Š“
value % 2 == 0

Mana programmÄ“Å”anas pieredze Go nav Ä«paÅ”i plaÅ”a, tikai nedaudz vairāk par pusotru gadu, es to izmantoju, lai gan bieži, bet tÄ«ri utilitāriem nolÅ«kiem (nu, varbÅ«t izņemot vienu projektu, kas saistÄ«ts ar augstas slodzes http servisu), tāpēc es sākās ar to. Atveriet GoLand un uzrakstiet vienkārÅ”u testu


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
}

Iegūstam rezultātu, kas parāda, jo augstāks slieksnis, jo biežāk parādās veiktspējas svārstības.

Salīdzinātmax 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

Ir skaidrs, ka Å”ajā gadÄ«jumā dažādiem sliekŔņiem mums ir dažādas testa datu kopas, procesora slodze (manā klēpjdatorā i5-2540M) svārstās ap 20..30%, atmiņa, ko aizņem lietojumprogramma, kas darbojas no GoLand, ir vidēji. apmēram 813 MB - tas ietekmē arÄ« rezultāta ticamÄ«bu, jums ir jāsaglabā testa gadÄ«jumi diskā un jāveic visi testi katram slieksnim atseviŔķi viens no otra.

Un tagad, domājot, kā to visu īstenot ar minimālām izmaksām, automātiski laboju stāvokļa pārbaudi

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

par

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

Izpildu testus vēlreiz... un vairs neko nesaprotu :)

Izpildei pavadÄ«tais laiks sāk atŔķirties nevis par procentiem/procentu daļām, bet par 10..15%.Ātri pievienoju vēl 2 testus:

		
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
}

Es to palaižu un iegÅ«stu Å”o attēlu:sākotnējā masÄ«va ietilpÄ«ba: 100000000

maksimālais slieksnis: 128
maxEvenDividing rezultāts: 126 ilgums 116.0066 ms
maxEvenDividing2 rezultāts: 126 ilgums 79.0045 ms
maxEvenConjunction rezultāts: 126 ilgums 114.0065 ms
maxEvenConjunction2 rezultāts: 126 ilgums 83.0048 ms

maksimālais slieksnis: 256
maxEvenDividing rezultāts: 254 ilgums 111.0063 ms
maxEvenDividing2 rezultāts: 254 ilgums 77.0044 ms
maxEvenConjunction rezultāts: 254 ilgums 110.0063 ms
maxEvenConjunction2 rezultāts: 254 ilgums 80.0046 ms

maksimālais slieksnis: 512
maxEvenDividing rezultāts: 510 ilgums 114.0066 ms
maxEvenDividing2 rezultāts: 510 ilgums 80.0045 ms
maxEvenConjunction rezultāts: 510 ilgums 110.0063 ms
maxEvenConjunction2 rezultāts: 510 ilgums 80.0046 ms

maksimālais slieksnis: 1024
maxEvenDividing rezultāts: 1022 ilgums 109.0063 ms
maxEvenDividing2 rezultāts: 1022 ilgums 77.0044 ms
maxEvenConjunction rezultāts: 1022 ilgums 111.0063 ms
maxEvenConjunction2 rezultāts: 1022 ilgums 81.0047 ms

maksimālais slieksnis: 2048
maxEvenDividing rezultāts: 2046 ilgums 114.0065 ms
maxEvenDividing2 rezultāts: 2046 ilgums 79.0045 ms
maxEvenConjunction rezultāts: 2046 ilgums 113.0065 ms
maxEvenConjunction2 rezultāts: 2046 ilgums 81.0046 ms

maksimālais slieksnis: 4096
maxEvenDividing rezultāts: 4094 ilgums 114.0065 ms
maxEvenDividing2 rezultāts: 4094 ilgums 80.0046 ms
maxEvenConjunction rezultāts: 4094 ilgums 111.0063 ms
maxEvenConjunction2 rezultāts: 4094 ilgums 78.0045 ms

maksimālais slieksnis: 8192
maxEvenDividing rezultāts: 8190 ilgums 107.0062 ms
maxEvenDividing2 rezultāts: 8190 ilgums 77.0044 ms
maxEvenConjunction rezultāts: 8190 ilgums 111.0063 ms
maxEvenConjunction2 rezultāts: 8190 ilgums 77.0044 ms

maksimālais slieksnis: 16384
maxEvenDividing rezultāts: 16382 ilgums 109.0063 ms
maxEvenDividing2 rezultāts: 16382 ilgums 77.0044 ms
maxEvenConjunction rezultāts: 16382 ilgums 108.0062 ms
maxEvenConjunction2 rezultāts: 16382 ilgums 77.0044 ms

maksimālais slieksnis: 32768
maxEvenDividing rezultāts: 32766 ilgums 112.0064 ms
maxEvenDividing2 rezultāts: 32766 ilgums 77.0044 ms
maxEvenConjunction rezultāts: 32766 ilgums 109.0062 ms
maxEvenConjunction2 rezultāts: 32766 ilgums 78.0045 ms

maksimālais slieksnis: 65536
maxEvenDividing rezultāts: 65534 ilgums 109.0062 ms
maxEvenDividing2 rezultāts: 65534 ilgums 75.0043 ms
maxEvenConjunction rezultāts: 65534 ilgums 109.0063 ms
maxEvenConjunction2 rezultāts: 65534 ilgums 79.0045 ms

maksimālais slieksnis: 131072
maxEvenDividing rezultāts: 131070 ilgums 108.0061 ms
maxEvenDividing2 rezultāts: 131070 ilgums 76.0044 ms
maxEvenConjunction rezultāts: 131070 ilgums 110.0063 ms
maxEvenConjunction2 rezultāts: 131070 ilgums 80.0046 ms

maksimālais slieksnis: 262144
maxEvenDividing rezultāts: 262142 ilgums 110.0063 ms
maxEvenDividing2 rezultāts: 262142 ilgums 76.0044 ms
maxEvenConjunction rezultāts: 262142 ilgums 107.0061 ms
maxEvenConjunction2 rezultāts: 262142 ilgums 78.0044 ms

maksimālais slieksnis: 524288
maxEvenDividing rezultāts: 524286 ilgums 109.0062 ms
maxEvenDividing2 rezultāts: 524286 ilgums 78.0045 ms
maxEvenConjunction rezultāts: 524286 ilgums 109.0062 ms
maxEvenConjunction2 rezultāts: 524286 ilgums 80.0046 ms

maksimālais slieksnis: 1048576
maxEvenDividing rezultāts: 1048574 ilgums 109.0063 ms
maxEvenDividing2 rezultāts: 1048574 ilgums 80.0045 ms
maxEvenConjunction rezultāts: 1048574 ilgums 114.0066 ms
maxEvenConjunction2 rezultāts: 1048574 ilgums 78.0044 ms

maksimālais slieksnis: 2097152
maxEvenDividing rezultāts: 2097150 ilgums 111.0064 ms
maxEvenDividing2 rezultāts: 2097150 ilgums 79.0045 ms
maxEvenConjunction rezultāts: 2097150 ilgums 112.0064 ms
maxEvenConjunction2 rezultāts: 2097150 ilgums 77.0044 ms

maksimālais slieksnis: 4194304
maxEvenDividing rezultāts: 4194302 ilgums 111.0063 ms
maxEvenDividing2 rezultāts: 4194302 ilgums 78.0045 ms
maxEvenConjunction rezultāts: 4194302 ilgums 111.0063 ms
maxEvenConjunction2 rezultāts: 4194302 ilgums 77.0044 ms

maksimālais slieksnis: 8388608
maxEvenDividing rezultāts: 8388606 ilgums 109.0062 ms
maxEvenDividing2 rezultāts: 8388606 ilgums 78.0045 ms
maxEvenConjunction rezultāts: 8388606 ilgums 114.0065 ms
maxEvenConjunction2 rezultāts: 8388606 ilgums 78.0045 ms

maksimālais slieksnis: 16777216
maxEvenDividing rezultāts: 16777214 ilgums 109.0062 ms
maxEvenDividing2 rezultāts: 16777214 ilgums 77.0044 ms
maxEvenConjunction rezultāts: 16777214 ilgums 109.0063 ms
maxEvenConjunction2 rezultāts: 16777214 ilgums 77.0044 ms

maksimālais slieksnis: 33554432
maxEvenDividing rezultāts: 33554430 ilgums 113.0065 ms
maxEvenDividing2 rezultāts: 33554430 ilgums 78.0045 ms
maxEvenConjunction rezultāts: 33554430 ilgums 110.0063 ms
maxEvenConjunction2 rezultāts: 33554430 ilgums 80.0045 ms

maksimālais slieksnis: 67108864
maxEvenDividing rezultāts: 67108860 ilgums 112.0064 ms
maxEvenDividing2 rezultāts: 67108860 ilgums 77.0044 ms
maxEvenConjunction rezultāts: 67108860 ilgums 112.0064 ms
maxEvenConjunction2 rezultāts: 67108860 ilgums 80.0046 ms

maksimālais slieksnis: 134217728
maxEvenDividing rezultāts: 134217726 ilgums 109.0063 ms
maxEvenDividing2 rezultāts: 134217726 ilgums 78.0044 ms
maxEvenConjunction rezultāts: 134217726 ilgums 114.0065 ms
maxEvenConjunction2 rezultāts: 134217726 ilgums 81.0047 ms

maksimālais slieksnis: 268435456
maxEvenDividing rezultāts: 268435446 ilgums 111.0064 ms
maxEvenDividing2 rezultāts: 268435446 ilgums 79.0045 ms
maxEvenConjunction rezultāts: 268435446 ilgums 114.0065 ms
maxEvenConjunction2 rezultāts: 268435446 ilgums 79.0045 ms

maksimālais slieksnis: 536870912
maxEvenDividing rezultāts: 536870910 ilgums 107.0062 ms
maxEvenDividing2 rezultāts: 536870910 ilgums 76.0043 ms
maxEvenConjunction rezultāts: 536870910 ilgums 109.0062 ms
maxEvenConjunction2 rezultāts: 536870910 ilgums 80.0046 ms

Es nevarēju atrast skaidru skaidrojumu, kāpēc Go kompilators neoptimizē kodu un vienmēr pārbauda otro nosacÄ«jumu, pat ja pirmais ir nepatiess. Vai varbÅ«t manas acis ir vienkārÅ”i izplÅ«duÅ”as un es neredzu nekādu acÄ«mredzamu kļūdu? Vai arÄ« jums ir jāsniedz daži Ä«paÅ”i norādÄ«jumi kompilatoram? PriecāŔos par saprātÄ«giem komentāriem.

PS: Jā, sava prieka pēc, es veica līdzīgus testus uz Java 5 un Java 7/8 - viss skaidrs, izpildes laiks ir vienāds.

Avots: www.habr.com

Pievieno komentāru