Kā jūs domājat, vai šie divi nosacījumu pārbaudes varianti iekš cikla ir līdzvērtīgi veiktspējā?
if a > b && c*2 > d {
....
}
// un
if a d {
....
}
Viss sākās ar "sīku smadzeņu treniņu", bija jāsniedz piemērs optimālai meklēšanai masīvā veselu skaitļu [-x….x] pēc lielākā pāra skaitļa. Man kļuva interesanti, cik daudz veiktspēja pieaugs, ja, lai noskaidrotu, vai skaitlis ir pāra vai nē, izmantos loģisko reizināšanu ar 1.
//у четных чисел последний бит всегда равен 0
value & 1 == 0
//vs классический метод
value % 2 == 0
Mans programmēšanas pieredze ar Go nav ļoti liela, nedaudz vairāk par pusotru gadu, es to izmantoju, lai gan bieži, bet tīri utilitārajiem mērķiem (nu, varbūt izņemot vienu projektu, kas saistīts ar augstslodzes http servisu), tāpēc es tieši ar to arī sāku. Atveram GoLand un rakstām 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("sākotnējā masīva kapacitāte: " + fmt.Sprint(size))
var maxValue int32
// Mēs variēsim skaitļu diapazonu no minimālā
// līdz maksimālajam. Jo mazāks diapazons, jo vairāk
// procesora laika tiks patērēts šī
// skaitļa salīdzināšanai, ar iepriekš atrasto un otrādi
for maxValue = 128; maxValue Saņemam rezultātu, kurā redzams, ka jo lielāks slieksnis, jo biežāk rodas fluktuācijas attiecībā uz veiktspēju.
Salīdzinietmaksimālā sliekšņa vērtība: 128
maxEvenDividing rezultāts: 126 ilgums 116.0067ms
maxEvenConjunction rezultāts: 126 ilgums 116.0066ms
maksimālais slieksnis: 16384
maxEvenDividing rezultāts: 16382 ilgums 115.0066ms
maxEvenConjunction rezultāts: 16382 ilgums 111.0064ms
......
maksimālais slieksnis: 8388608
maxEvenDividing rezultāts: 8388606 ilgums 109.0063ms
maxEvenConjunction rezultāts: 8388606 ilgums 109.0062ms
maksimālais slieksnis: 16777216
maxEvenDividing rezultāts: 16777214 ilgums 108.0062ms
maxEvenConjunction rezultāts: 16777214 ilgums 109.0062ms
maksimālais slieksnis: 33554432
maxEvenDividing rezultāts: 33554430 ilgums 114.0066ms
maxEvenConjunction rezultāts: 33554430 ilgums 110.0063ms
maksimālais slieksnis: 67108864
maxEvenDividing rezultāts: 67108860 ilgums 111.0064ms
maxEvenConjunction rezultāts: 67108860 ilgums 109.0062ms
maksimālais slieksnis: 134217728
maxEvenDividing rezultāts: 134217726 ilgums 108.0062ms
maxEvenConjunction rezultāts: 134217726 ilgums 109.0063ms
maksimālais slieksnis: 268435456
maxEvenDividing rezultāts: 268435446 ilgums 111.0063ms
maxEvenConjunction rezultāts: 268435446 ilgums 110.0063ms
Paskaidrojams, ka šajā gadījumā atšķirīgajiem sliekšņiem ir atšķirīgi testēšanas datu kopumi, procesora slodze (manā klēpjdatorā i5-2540M) svārstās ap 20..30%, atmiņa, ko patērē lietotne, palaižot to no GoLand, vidēji ir ap 813MB — tas arī ietekmē rezultāta ticamību, nepieciešams īstenot testēšanas datu kopu saglabāšanu diskā un izpildīt visus testus katram sliekšņa variantam izolēti viens no otra.
Un domājot par to, kā minimālās izmaksās to īstenot, es automātiski laboju nosacījuma pārbaudi
ja value > current && value&1 == 0 {
current = value
}
uz
ja value <= current {
continue;
}
ja value&1 == 0 {
current = value
}
es palaidu testus vēlreiz… un pārtraucu saprast, kas notiek 🙂
Izpildes laiks sāk atšķirties ne tikai par procentiem / daļām procenta, bet par 10..15%. Ātri pievienoju vēl 2 testus:
func maxEvenDividing2(name string, arr []int32) Rezultāts {
start := time.Now()
var current int32 = math.MinInt32
for _, value := range arr {
ja value <= current {
continue
}
ja value%2 == 0 {
current = value
}
}
duration := time.Since(start)
result := Rezultāts{name, duration, current}
return result
}
func maxEvenConjunction2(name string, arr []int32) Rezultāts {
start := time.Now()
var current int32 = math.MinInt32
for _, value := range arr {
ja value <= current {
continue
}
ja value&1 == 0 {
current = value
}
}
duration := time.Since(start)
result := Rezultāts{name, duration, current}
return result
}
es palaidu un saņemu šādu attēlu:sākotnējā masīva jauda: 100000000
maksimālā sliekšņa vērtība: 128
maxEvenDividing rezultāts: 126 ilgums 116.0066ms
maxEvenDividing2 rezultāts: 126 ilgums 79.0045ms
maxEvenConjunction rezultāts: 126 ilgums 114.0065ms
maxEvenConjunction2 rezultāts: 126 ilgums 83.0048ms
maksimālais slieksnis: 256
maxEvenDividing rezultāts: 254 ilgums 111.0063ms
maxEvenDividing2 rezultāts: 254 ilgums 77.0044ms
maxEvenConjunction rezultāts: 254 ilgums 110.0063ms
maxEvenConjunction2 rezultāts: 254 ilgums 80.0046ms
maksimālais slieksnis: 512
maxEvenDividing rezultāts: 510 ilgums 114.0066ms
maxEvenDividing2 rezultāts: 510 ilgums 80.0045ms
maxEvenConjunction rezultāts: 510 ilgums 110.0063ms
maxEvenConjunction2 rezultāts: 510 ilgums 80.0046ms
maksimālais slieksnis: 1024
maxEvenDividing rezultāts: 1022 ilgums 109.0063ms
maxEvenDividing2 rezultāts: 1022 ilgums 77.0044ms
maxEvenConjunction rezultāts: 1022 ilgums 111.0063ms
maxEvenConjunction2 rezultāts: 1022 ilgums 81.0047ms
maksimālais slieksnis: 2048
maxEvenDividing rezultāts: 2046 ilgums 114.0065ms
maxEvenDividing2 rezultāts: 2046 ilgums 79.0045ms
maxEvenConjunction rezultāts: 2046 ilgums 113.0065ms
maxEvenConjunction2 rezultāts: 2046 ilgums 81.0046ms
maksimālā robeža: 4096
maxEvenDividing rezultāts: 4094 ilgums 114.0065ms
maxEvenDividing2 rezultāts: 4094 ilgums 80.0046ms
maxEvenConjunction rezultāts: 4094 ilgums 111.0063ms
maxEvenConjunction2 rezultāts: 4094 ilgums 78.0045ms
maksimālā robeža: 8192
maxEvenDividing rezultāts: 8190 ilgums 107.0062ms
maxEvenDividing2 rezultāts: 8190 ilgums 77.0044ms
maxEvenConjunction rezultāts: 8190 ilgums 111.0063ms
maxEvenConjunction2 rezultāts: 8190 ilgums 77.0044ms
maksimālais slieksnis: 16384
maxEvenDividing rezultāts: 16382 ilgums 109.0063ms
maxEvenDividing2 rezultāts: 16382 ilgums 77.0044ms
maxEvenConjunction rezultāts: 16382 ilgums 108.0062ms
maxEvenConjunction2 rezultāts: 16382 ilgums 77.0044ms
maksimālā robeža: 32768
maxEvenDividing rezultāts: 32766 ilgums 112.0064ms
maxEvenDividing2 rezultāts: 32766 ilgums 77.0044ms
maxEvenConjunction rezultāts: 32766 ilgums 109.0062ms
maxEvenConjunction2 rezultāts: 32766 ilgums 78.0045ms
maksimālā robeža: 65536
maxEvenDividing rezultāts: 65534 ilgums 109.0062ms
maxEvenDividing2 rezultāts: 65534 ilgums 75.0043ms
maxEvenConjunction rezultāts: 65534 ilgums 109.0063ms
maxEvenConjunction2 rezultāts: 65534 ilgums 79.0045ms
maksimālā robeža: 131072
maxEvenDividing rezultāts: 131070 ilgums 108.0061ms
maxEvenDividing2 rezultāts: 131070 ilgums 76.0044ms
maxEvenConjunction rezultāts: 131070 ilgums 110.0063ms
maxEvenConjunction2 rezultāts: 131070 ilgums 80.0046ms
maksimālā robeža: 262144
maxEvenDividing rezultāts: 262142 ilgums 110.0063ms
maxEvenDividing2 rezultāts: 262142 ilgums 76.0044ms
maxEvenConjunction rezultāts: 262142 ilgums 107.0061ms
maxEvenConjunction2 rezultāts: 262142 ilgums 78.0044ms
maksimālā robeža: 524288
maxEvenDividing rezultāts: 524286 ilgums 109.0062ms
maxEvenDividing2 rezultāts: 524286 ilgums 78.0045ms
maxEvenConjunction rezultāts: 524286 ilgums 109.0062ms
maxEvenConjunction2 rezultāts: 524286 ilgums 80.0046ms
maksimālā robeža: 1048576
maxEvenDividing rezultāts: 1048574 ilgums 109.0063ms
maxEvenDividing2 rezultāts: 1048574 ilgums 80.0045ms
maxEvenConjunction rezultāts: 1048574 ilgums 114.0066ms
maxEvenConjunction2 rezultāts: 1048574 ilgums 78.0044ms
maksimālā robeža: 2097152
maxEvenDividing rezultāts: 2097150 ilgums 111.0064ms
maxEvenDividing2 rezultāts: 2097150 ilgums 79.0045ms
maxEvenConjunction rezultāts: 2097150 ilgums 112.0064ms
maxEvenConjunction2 rezultāts: 2097150 ilgums 77.0044ms
maksimālā robeža: 4194304
maxEvenDividing rezultāts: 4194302 ilgums 111.0063ms
maxEvenDividing2 rezultāts: 4194302 ilgums 78.0045ms
maxEvenConjunction rezultāts: 4194302 ilgums 111.0063ms
maxEvenConjunction2 rezultāts: 4194302 ilgums 77.0044ms
maksimālais slieksnis: 8388608
maxEvenDividing rezultāts: 8388606 ilgums 109.0062ms
maxEvenDividing2 rezultāts: 8388606 ilgums 78.0045ms
maxEvenConjunction rezultāts: 8388606 ilgums 114.0065ms
maxEvenConjunction2 rezultāts: 8388606 ilgums 78.0045ms
maksimālais slieksnis: 16777216
maxEvenDividing rezultāts: 16777214 ilgums 109.0062ms
maxEvenDividing2 rezultāts: 16777214 ilgums 77.0044ms
maxEvenConjunction rezultāts: 16777214 ilgums 109.0063ms
maxEvenConjunction2 rezultāts: 16777214 ilgums 77.0044ms
maksimālais slieksnis: 33554432
maxEvenDividing rezultāts: 33554430 ilgums 113.0065ms
maxEvenDividing2 rezultāts: 33554430 ilgums 78.0045ms
maxEvenConjunction rezultāts: 33554430 ilgums 110.0063ms
maxEvenConjunction2 rezultāts: 33554430 ilgums 80.0045ms
maksimālais slieksnis: 67108864
maxEvenDividing rezultāts: 67108860 ilgums 112.0064ms
maxEvenDividing2 rezultāts: 67108860 ilgums 77.0044ms
maxEvenConjunction rezultāts: 67108860 ilgums 112.0064ms
maxEvenConjunction2 rezultāts: 67108860 ilgums 80.0046ms
maksimālais slieksnis: 134217728
maxEvenDividing rezultāts: 134217726 ilgums 109.0063ms
maxEvenDividing2 rezultāts: 134217726 ilgums 78.0044ms
maxEvenConjunction rezultāts: 134217726 ilgums 114.0065ms
maxEvenConjunction2 rezultāts: 134217726 ilgums 81.0047ms
maksimālais slieksnis: 268435456
maxEvenDividing rezultāts: 268435446 ilgums 111.0064ms
maxEvenDividing2 rezultāts: 268435446 ilgums 79.0045ms
maxEvenConjunction rezultāts: 268435446 ilgums 114.0065ms
maxEvenConjunction2 rezultāts: 268435446 ilgums 79.0045ms
maksimālā robeža: 536870912
maxEvenDividing rezultāts: 536870910 ilgums 107.0062ms
maxEvenDividing2 rezultāts: 536870910 ilgums 76.0043ms
maxEvenConjunction rezultāts: 536870910 ilgums 109.0062ms
maxEvenConjunction2 rezultāts: 536870910 ilgums 80.0046ms
Es neatradu saprotamu skaidrojumu, kāpēc Go kompilators neoptimizē kodu un vienmēr pārbauda otro nosacījumu, pat ja pirmais ir nepaties. Varbūt mans acs ir "apmācies", un es neredzu kādu acīmredzamu kļūdu? Vai varbūt ir jānorāda kādas īpašas instrukcijas kompilatoram? Būtu prieks par saprotamiem komentāriem.
PS: Jā, interesanta nolūkā, es veicu līdzīgus testus Java 5 un Java 7/8 — viss ir skaidrs, izpildes laiks ir vienāds.
Avots: habr.com
