Permalink
Browse files

cmd/syncthing: Add selectable sha256 package (fixes syncthing#3613, f…

…ixes syncthing#3614)

This adds autodetection of the fastest hashing library on startup, thus
handling the performance regression. It also adds an environment
variable to control the selection, STHASHING=standard (Go standard
library version, avoids SIGILL crash when the minio library has bugs on
odd CPUs), STHASHING=minio (to force using the minio version) or unset
for the default autodetection.
  • Loading branch information...
calmh committed Sep 22, 2016
1 parent 5f01afb commit dda6a84cadcb71fe18f8d6693b23554a1711e5b4
View
@@ -41,6 +41,7 @@ import (
"github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/sha256"
"github.com/syncthing/syncthing/lib/symlinks"
"github.com/syncthing/syncthing/lib/tlsutil"
"github.com/syncthing/syncthing/lib/upgrade"
@@ -166,6 +167,11 @@ are mostly useful for developers. Use with care.
STNOUPGRADE Disable automatic upgrades.
STHASHING Select the SHA256 hashing package to use. Possible values
are "standard" for the Go standard library implementation,
"minio" for the github.com/minio/sha256-simd implementation,
and blank (the default) for auto detection.
GOMAXPROCS Set the maximum number of CPU cores to use. Defaults to all
available CPU cores.
@@ -853,7 +859,7 @@ func printHashRate() {
decimals = 1
}
l.Infof("Single thread hash performance is ~%.*f MB/s", decimals, hashRate)
l.Infof("Single thread hash performance is ~%.*f MB/s (%s).", decimals, hashRate, sha256.Selected)
}
func loadConfig() (*config.Wrapper, error) {
@@ -18,12 +18,11 @@ import (
"strings"
"time"
"github.com/minio/sha256-simd"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/dialer"
"github.com/syncthing/syncthing/lib/model"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/sha256"
"github.com/syncthing/syncthing/lib/upgrade"
"github.com/thejerf/suture"
)
@@ -12,9 +12,8 @@ import (
"fmt"
"time"
"github.com/minio/sha256-simd"
"github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/sha256"
)
const (
View
@@ -11,7 +11,7 @@ import (
"regexp"
"strings"
"github.com/minio/sha256-simd"
"github.com/syncthing/syncthing/lib/sha256"
"github.com/calmh/luhn"
)
View
@@ -11,9 +11,8 @@ import (
"fmt"
"io"
"github.com/minio/sha256-simd"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/sha256"
)
var SHA256OfNothing = []uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}
View
@@ -0,0 +1,96 @@
// Copyright (C) 2016 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package sha256
import (
"crypto/rand"
cryptoSha256 "crypto/sha256"
"hash"
"os"
"time"
minioSha256 "github.com/minio/sha256-simd"
)
func init() {
switch os.Getenv("STHASHING") {
case "":
// When unset, probe for the fastest implementation.
selectFastest()
case "minio":
// When set to "minio", use that.
selectMinio()
default:
// When set to anything else, such as "default", use the default Go implementation.
}
}
const BlockSize = cryptoSha256.BlockSize
const Size = cryptoSha256.Size
const Size224 = cryptoSha256.Size224
// May be switched out for another implementation
var New func() hash.Hash = cryptoSha256.New
var Sum256 func(data []byte) [Size]byte = cryptoSha256.Sum256
func New224() hash.Hash {
// Will be inlined
return cryptoSha256.New224()
}
func Sum224(data []byte) (sum224 [Size224]byte) {
// Will be inlined
return cryptoSha256.Sum224(data)
}
var Selected = "crypto/sha256"
var CryptoPerf float64
var MinioPerf float64
func selectFastest() {
CryptoPerf = cpuBench(cryptoSha256.New)
MinioPerf = cpuBench(minioSha256.New)
if MinioPerf > 1.05*CryptoPerf {
selectMinio()
}
}
func selectMinio() {
New = minioSha256.New
Sum256 = minioSha256.Sum256
Selected = "github.com/minio/sha256-simd"
}
func cpuBench(newFn func() hash.Hash) float64 {
const iterations = 3
const duration = 75 * time.Millisecond
var perf float64
for i := 0; i < iterations; i++ {
if v := cpuBenchOnce(duration, newFn); v > perf {
perf = v
}
}
return perf
}
func cpuBenchOnce(duration time.Duration, newFn func() hash.Hash) float64 {
chunkSize := 100 * 1 << 10
h := newFn()
bs := make([]byte, chunkSize)
rand.Reader.Read(bs)
t0 := time.Now()
b := 0
for time.Since(t0) < duration {
h.Write(bs)
b += chunkSize
}
h.Sum(nil)
d := time.Since(t0)
return float64(int(float64(b)/d.Seconds()/(1<<20)*100)) / 100
}
@@ -20,7 +20,7 @@ import (
"io"
"math/big"
"github.com/minio/sha256-simd"
"github.com/syncthing/syncthing/lib/sha256"
)
// GenerateKeys returns a new key pair, with the private and public key

0 comments on commit dda6a84

Please sign in to comment.