2017-02-19 2 views
1

Ich war neugierig, ob jemand versucht hat, in Go vor pool Karten zu gehen? Ich habe vorher über pooling buffers gelesen, und ich fragte mich, ob es durch ähnliche Argumentation sinnvoll wäre, Karten zu sammeln, wenn man sie häufig erstellen und zerstören muss oder wenn es irgendeinen Grund gibt, warum es a priori nicht effizient ist. Wenn eine Map in den Pool zurückgegeben wird, müsste man sie durchlaufen und alle Elemente löschen, aber es scheint, dass eine beliebte Empfehlung zu create a new map instead of deleting the entries in a map which has already been allocated and reusing it ist, die mich denken lässt, dass das Poolen von Karten nicht so vorteilhaft ist.Pooling Karten in Golang

Antwort

1

Wenn sich Ihre Karten durch das Löschen oder Hinzufügen von Einträgen stark ändern, führt dies zu neuen Zuweisungen und es wird keinen Vorteil haben, diese zu poolen.

Wenn sich die Größe Ihrer Karten nicht ändert, aber nur die Werte der Schlüssel geändert werden, ist das Pooling eine erfolgreiche Optimierung.

Dies funktioniert gut, wenn Sie tabellenartige Strukturen lesen, z. B. CSV-Dateien oder Datenbanktabellen. Jede Zeile enthält genau die gleichen Spalten, sodass Sie keine Einträge löschen müssen.

Die Benchmark zeigt keine Zuordnung, wenn sie mit go test -benchmem -bench . zu

package mappool 

import "testing" 

const SIZE = 1000000 

func BenchmarkMap(b *testing.B) { 
    m := make(map[int]int) 

    for i := 0; i < SIZE; i++ { 
     m[i] = i 
    } 

    b.ResetTimer() 

    for i := 0; i < b.N; i++ { 
     for i := 0; i < SIZE; i++ { 
      m[i] = m[i] + 1 
     } 
    } 
} 
1

Wie @Grzegorz Žur sagt laufen, wenn Sie Ihre Karten nicht viel sehr groß ändern, dann hilfreich Pooling. Um dies zu testen, habe ich einen Benchmark erstellt, bei dem sich das Pooling durchsetzt. Die Ausgabe auf meiner Maschine ist:

Pool time: 115.977µs 
No-pool time: 160.828µs 

Benchmark-Code:

package main 

import (
    "fmt" 
    "math/rand" 
    "time" 
) 

const BenchIters = 1000 

func main() { 
    pool := map[int]int{} 
    poolTime := benchmark(func() { 
     useMapForSomething(pool) 

     // Return to pool by clearing the map. 
     for key := range pool { 
      delete(pool, key) 
     } 
    }) 

    nopoolTime := benchmark(func() { 
     useMapForSomething(map[int]int{}) 
    }) 

    fmt.Println("Pool time:", poolTime) 
    fmt.Println("No-pool time:", nopoolTime) 
} 

func useMapForSomething(m map[int]int) { 
    for i := 0; i < 1000; i++ { 
     m[rand.Intn(300)] += 5 
    } 
} 

// benchmark measures how long f takes, on average. 
func benchmark(f func()) time.Duration { 
    start := time.Now().UnixNano() 
    for i := 0; i < BenchIters; i++ { 
     f() 
    } 
    return time.Nanosecond * time.Duration((time.Now().UnixNano()-start)/BenchIters) 
}