/
hasher.go
103 lines (91 loc) · 1.87 KB
/
hasher.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package datatree
import (
"sync"
"sync/atomic"
"runtime"
sha256 "github.com/minio/sha256-simd"
)
const (
MinimumJobsInGoroutine = 20
MaximumGoroutines = 16
)
func hash(in []byte) []byte {
h := sha256.New()
h.Write(in)
return h.Sum(nil)
}
func hash2(level byte, a, b []byte) []byte {
h := sha256.New()
h.Write([]byte{level})
h.Write(a)
h.Write(b)
return h.Sum(nil)
}
type hashJob struct {
target []byte
level byte
srcA []byte
srcB []byte
}
func (job hashJob) run() {
h := sha256.New()
h.Write([]byte{job.level})
h.Write(job.srcA)
h.Write(job.srcB)
copy(job.target, h.Sum(nil))
}
type Hasher struct {
jobs []hashJob
//wg sync.WaitGroup
}
func (h *Hasher) Add(level byte, target, srcA, srcB []byte) {
h.jobs = append(h.jobs, hashJob{target, level, srcA, srcB})
}
func (h *Hasher) Run() {
if len(h.jobs) < MinimumJobsInGoroutine {
for _, job := range h.jobs {
job.run()
}
}
//stripe := MinimumJobsInGoroutine
//if stripe*MaximumGoroutines < len(h.jobs) {
// stripe = len(h.jobs) / MaximumGoroutines
// if len(h.jobs)%MaximumGoroutines != 0 {
// stripe++
// }
//}
//for start := 0; start < len(h.jobs); start += stripe {
// end := start + stripe
// if end > len(h.jobs) {
// end = len(h.jobs)
// }
// h.wg.Add(1)
// go func(start, end int) { //copy start and end to prevent race condition
// for _, job := range h.jobs[start:end] {
// job.run()
// }
// h.wg.Done()
// }(start, end)
//}
//h.wg.Wait()
sharedIdx := int64(-1)
ParrallelRun(runtime.NumCPU(), func(workerID int) {
for {
myIdx := atomic.AddInt64(&sharedIdx, 1)
if myIdx >= int64(len(h.jobs)) {return}
h.jobs[myIdx].run()
}
})
h.jobs = h.jobs[:0]
}
func ParrallelRun(workerCount int, fn func(workerID int)) {
var wg sync.WaitGroup
wg.Add(workerCount)
for i := 0; i < workerCount; i++ {
go func(i int) {
fn(i)
wg.Done()
}(i)
}
wg.Wait()
}