-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
128 lines (106 loc) · 2.17 KB
/
main.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package main
import (
"crypto/rand"
"crypto/sha256"
"flag"
"fmt"
"hash"
"log"
"runtime"
"sync"
_ "github.com/ianlancetaylor/cgosymbolizer"
"github.com/pkg/profile"
"github.com/spacemonkeygo/openssl"
)
var _ hash.Hash = (*openSSLSHA256Hash)(nil)
type openSSLSHA256Hash struct {
*openssl.SHA256Hash
}
func (h *openSSLSHA256Hash) BlockSize() int { return sha256.BlockSize }
func (h *openSSLSHA256Hash) Reset() {
if err := h.SHA256Hash.Reset(); err != nil {
panic(err)
}
}
func (h *openSSLSHA256Hash) Size() int { return sha256.Size }
func (h *openSSLSHA256Hash) Sum(p []byte) []byte {
s, err := h.SHA256Hash.Sum()
if err != nil {
panic(err)
}
return append(p, s[:]...)
}
func newOpenSSLSHA256Hash() hash.Hash {
h, err := openssl.NewSHA256Hash()
if err != nil {
panic(err)
}
return &openSSLSHA256Hash{
SHA256Hash: h,
}
}
func compute(pool *sync.Pool, data []byte) ([]byte, error) {
h := pool.Get().(hash.Hash)
defer pool.Put(h)
h.Reset()
_, err := h.Write(data)
if err != nil {
return nil, err
}
return h.Sum(nil), nil
}
func main() {
useProfiler := flag.Bool("profiler", false, "enable CPU profiler")
flag.Parse()
// setup profiler
if *useProfiler {
options := []func(*profile.Profile){
profile.ProfilePath("."),
profile.NoShutdownHook,
profile.CPUProfile,
}
profiler := profile.Start(options...)
defer profiler.Stop()
}
// setup input
const dataSize = 1024 * 4
input := make([]byte, dataSize)
_, err := rand.Read(input)
if err != nil {
log.Fatal(err)
}
// setup hash pool to reuse hashers
hashPool := &sync.Pool{
New: func() interface{} { return newOpenSSLSHA256Hash() },
}
inputChan := make(chan []byte)
outputChan := make(chan []byte)
tasks := 1024 * 1024
workers := runtime.NumCPU()
for i := 0; i < workers; i++ {
go func() {
for {
data, ok := <-inputChan
if !ok {
return
}
output, err := compute(hashPool, data)
if err != nil {
log.Fatal(err)
}
outputChan <- output
}
}()
}
go func() {
for i := 0; i < tasks; i++ {
inputChan <- input
}
close(inputChan)
}()
var output []byte
for i := 0; i < tasks; i++ {
output = <-outputChan
}
fmt.Println(output)
}