Merge pull request #316 from mrd0ll4r/remove-time-now
Remove most calls to time.Now
This commit is contained in:
commit
1cc0738cbe
4 changed files with 100 additions and 32 deletions
|
@ -40,6 +40,10 @@ chihaya:
|
||||||
read_timeout: 5s
|
read_timeout: 5s
|
||||||
write_timeout: 5s
|
write_timeout: 5s
|
||||||
|
|
||||||
|
# Whether to time requests.
|
||||||
|
# Disabling this should increase performance/decrease load.
|
||||||
|
enable_request_timing: false
|
||||||
|
|
||||||
# This block defines configuration for the tracker's UDP interface.
|
# This block defines configuration for the tracker's UDP interface.
|
||||||
# If you do not wish to run this, delete this section.
|
# If you do not wish to run this, delete this section.
|
||||||
udp:
|
udp:
|
||||||
|
@ -57,6 +61,10 @@ chihaya:
|
||||||
# The key used to encrypt connection IDs.
|
# The key used to encrypt connection IDs.
|
||||||
private_key: "paste a random string here that will be used to hmac connection IDs"
|
private_key: "paste a random string here that will be used to hmac connection IDs"
|
||||||
|
|
||||||
|
# Whether to time requests.
|
||||||
|
# Disabling this should increase performance/decrease load.
|
||||||
|
enable_request_timing: false
|
||||||
|
|
||||||
# This block defines configuration used for the storage of peer data.
|
# This block defines configuration used for the storage of peer data.
|
||||||
storage:
|
storage:
|
||||||
# The frequency which stale peers are removed.
|
# The frequency which stale peers are removed.
|
||||||
|
|
|
@ -62,25 +62,27 @@ func recordResponseDuration(action string, af *bittorrent.AddressFamily, err err
|
||||||
// Config represents all of the configurable options for an HTTP BitTorrent
|
// Config represents all of the configurable options for an HTTP BitTorrent
|
||||||
// Frontend.
|
// Frontend.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Addr string `yaml:"addr"`
|
Addr string `yaml:"addr"`
|
||||||
ReadTimeout time.Duration `yaml:"read_timeout"`
|
ReadTimeout time.Duration `yaml:"read_timeout"`
|
||||||
WriteTimeout time.Duration `yaml:"write_timeout"`
|
WriteTimeout time.Duration `yaml:"write_timeout"`
|
||||||
AllowIPSpoofing bool `yaml:"allow_ip_spoofing"`
|
AllowIPSpoofing bool `yaml:"allow_ip_spoofing"`
|
||||||
RealIPHeader string `yaml:"real_ip_header"`
|
RealIPHeader string `yaml:"real_ip_header"`
|
||||||
TLSCertPath string `yaml:"tls_cert_path"`
|
TLSCertPath string `yaml:"tls_cert_path"`
|
||||||
TLSKeyPath string `yaml:"tls_key_path"`
|
TLSKeyPath string `yaml:"tls_key_path"`
|
||||||
|
EnableRequestTiming bool `yaml:"enable_request_timing"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogFields renders the current config as a set of Logrus fields.
|
// LogFields renders the current config as a set of Logrus fields.
|
||||||
func (cfg Config) LogFields() log.Fields {
|
func (cfg Config) LogFields() log.Fields {
|
||||||
return log.Fields{
|
return log.Fields{
|
||||||
"addr": cfg.Addr,
|
"addr": cfg.Addr,
|
||||||
"readTimeout": cfg.ReadTimeout,
|
"readTimeout": cfg.ReadTimeout,
|
||||||
"writeTimeout": cfg.WriteTimeout,
|
"writeTimeout": cfg.WriteTimeout,
|
||||||
"allowIPSpoofing": cfg.AllowIPSpoofing,
|
"allowIPSpoofing": cfg.AllowIPSpoofing,
|
||||||
"realIPHeader": cfg.RealIPHeader,
|
"realIPHeader": cfg.RealIPHeader,
|
||||||
"tlsCertPath": cfg.TLSCertPath,
|
"tlsCertPath": cfg.TLSCertPath,
|
||||||
"tlsKeyPath": cfg.TLSKeyPath,
|
"tlsKeyPath": cfg.TLSKeyPath,
|
||||||
|
"enableRequestTiming": cfg.EnableRequestTiming,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,9 +170,18 @@ func (f *Frontend) listenAndServe() error {
|
||||||
// announceRoute parses and responds to an Announce.
|
// announceRoute parses and responds to an Announce.
|
||||||
func (f *Frontend) announceRoute(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
func (f *Frontend) announceRoute(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
var err error
|
var err error
|
||||||
start := time.Now()
|
var start time.Time
|
||||||
|
if f.EnableRequestTiming {
|
||||||
|
start = time.Now()
|
||||||
|
}
|
||||||
var af *bittorrent.AddressFamily
|
var af *bittorrent.AddressFamily
|
||||||
defer func() { recordResponseDuration("announce", af, err, time.Since(start)) }()
|
defer func() {
|
||||||
|
if f.EnableRequestTiming {
|
||||||
|
recordResponseDuration("announce", af, err, time.Since(start))
|
||||||
|
} else {
|
||||||
|
recordResponseDuration("announce", af, err, time.Duration(0))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
req, err := ParseAnnounce(r, f.RealIPHeader, f.AllowIPSpoofing)
|
req, err := ParseAnnounce(r, f.RealIPHeader, f.AllowIPSpoofing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -198,9 +209,18 @@ func (f *Frontend) announceRoute(w http.ResponseWriter, r *http.Request, _ httpr
|
||||||
// scrapeRoute parses and responds to a Scrape.
|
// scrapeRoute parses and responds to a Scrape.
|
||||||
func (f *Frontend) scrapeRoute(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
func (f *Frontend) scrapeRoute(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
var err error
|
var err error
|
||||||
start := time.Now()
|
var start time.Time
|
||||||
|
if f.EnableRequestTiming {
|
||||||
|
start = time.Now()
|
||||||
|
}
|
||||||
var af *bittorrent.AddressFamily
|
var af *bittorrent.AddressFamily
|
||||||
defer func() { recordResponseDuration("scrape", af, err, time.Since(start)) }()
|
defer func() {
|
||||||
|
if f.EnableRequestTiming {
|
||||||
|
recordResponseDuration("scrape", af, err, time.Since(start))
|
||||||
|
} else {
|
||||||
|
recordResponseDuration("scrape", af, err, time.Duration(0))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
req, err := ParseScrape(r)
|
req, err := ParseScrape(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -67,19 +67,21 @@ func recordResponseDuration(action string, af *bittorrent.AddressFamily, err err
|
||||||
// Config represents all of the configurable options for a UDP BitTorrent
|
// Config represents all of the configurable options for a UDP BitTorrent
|
||||||
// Tracker.
|
// Tracker.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Addr string `yaml:"addr"`
|
Addr string `yaml:"addr"`
|
||||||
PrivateKey string `yaml:"private_key"`
|
PrivateKey string `yaml:"private_key"`
|
||||||
MaxClockSkew time.Duration `yaml:"max_clock_skew"`
|
MaxClockSkew time.Duration `yaml:"max_clock_skew"`
|
||||||
AllowIPSpoofing bool `yaml:"allow_ip_spoofing"`
|
AllowIPSpoofing bool `yaml:"allow_ip_spoofing"`
|
||||||
|
EnableRequestTiming bool `yaml:"enable_request_timing"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogFields renders the current config as a set of Logrus fields.
|
// LogFields renders the current config as a set of Logrus fields.
|
||||||
func (cfg Config) LogFields() log.Fields {
|
func (cfg Config) LogFields() log.Fields {
|
||||||
return log.Fields{
|
return log.Fields{
|
||||||
"addr": cfg.Addr,
|
"addr": cfg.Addr,
|
||||||
"privateKey": cfg.PrivateKey,
|
"privateKey": cfg.PrivateKey,
|
||||||
"maxClockSkew": cfg.MaxClockSkew,
|
"maxClockSkew": cfg.MaxClockSkew,
|
||||||
"allowIPSpoofing": cfg.AllowIPSpoofing,
|
"allowIPSpoofing": cfg.AllowIPSpoofing,
|
||||||
|
"enableRequestTiming": cfg.EnableRequestTiming,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,13 +203,20 @@ func (t *Frontend) listenAndServe() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the request.
|
// Handle the request.
|
||||||
start := time.Now()
|
var start time.Time
|
||||||
|
if t.EnableRequestTiming {
|
||||||
|
start = time.Now()
|
||||||
|
}
|
||||||
action, af, err := t.handleRequest(
|
action, af, err := t.handleRequest(
|
||||||
// Make sure the IP is copied, not referenced.
|
// Make sure the IP is copied, not referenced.
|
||||||
Request{buffer[:n], append([]byte{}, addr.IP...)},
|
Request{buffer[:n], append([]byte{}, addr.IP...)},
|
||||||
ResponseWriter{t.socket, addr},
|
ResponseWriter{t.socket, addr},
|
||||||
)
|
)
|
||||||
recordResponseDuration(action, af, err, time.Since(start))
|
if t.EnableRequestTiming {
|
||||||
|
recordResponseDuration(action, af, err, time.Since(start))
|
||||||
|
} else {
|
||||||
|
recordResponseDuration(action, af, err, time.Duration(0))
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
|
@ -99,6 +100,25 @@ func New(cfg Config) (storage.PeerStore, error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
ps.wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer ps.wg.Done()
|
||||||
|
t := time.NewTicker(1 * time.Second)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ps.closing:
|
||||||
|
t.Stop()
|
||||||
|
select {
|
||||||
|
case <-t.C:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return
|
||||||
|
case now := <-t.C:
|
||||||
|
ps.setClock(now.UnixNano())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
return ps, nil
|
return ps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,11 +138,22 @@ type swarm struct {
|
||||||
type peerStore struct {
|
type peerStore struct {
|
||||||
shards []*peerShard
|
shards []*peerShard
|
||||||
closing chan struct{}
|
closing chan struct{}
|
||||||
wg sync.WaitGroup
|
// clock stores the current time nanoseconds, updated every second.
|
||||||
|
// Must be accessed atomically!
|
||||||
|
clock int64
|
||||||
|
wg sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ storage.PeerStore = &peerStore{}
|
var _ storage.PeerStore = &peerStore{}
|
||||||
|
|
||||||
|
func (ps *peerStore) getClock() int64 {
|
||||||
|
return atomic.LoadInt64(&ps.clock)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *peerStore) setClock(to int64) {
|
||||||
|
atomic.StoreInt64(&ps.clock, to)
|
||||||
|
}
|
||||||
|
|
||||||
func (ps *peerStore) shardIndex(infoHash bittorrent.InfoHash, af bittorrent.AddressFamily) uint32 {
|
func (ps *peerStore) shardIndex(infoHash bittorrent.InfoHash, af bittorrent.AddressFamily) uint32 {
|
||||||
// There are twice the amount of shards specified by the user, the first
|
// There are twice the amount of shards specified by the user, the first
|
||||||
// half is dedicated to IPv4 swarms and the second half is dedicated to
|
// half is dedicated to IPv4 swarms and the second half is dedicated to
|
||||||
|
@ -181,7 +212,7 @@ func (ps *peerStore) PutSeeder(ih bittorrent.InfoHash, p bittorrent.Peer) error
|
||||||
recordInfohashesDelta(1)
|
recordInfohashesDelta(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
shard.swarms[ih].seeders[pk] = time.Now().UnixNano()
|
shard.swarms[ih].seeders[pk] = ps.getClock()
|
||||||
|
|
||||||
shard.Unlock()
|
shard.Unlock()
|
||||||
return nil
|
return nil
|
||||||
|
@ -240,7 +271,7 @@ func (ps *peerStore) PutLeecher(ih bittorrent.InfoHash, p bittorrent.Peer) error
|
||||||
recordInfohashesDelta(1)
|
recordInfohashesDelta(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
shard.swarms[ih].leechers[pk] = time.Now().UnixNano()
|
shard.swarms[ih].leechers[pk] = ps.getClock()
|
||||||
|
|
||||||
shard.Unlock()
|
shard.Unlock()
|
||||||
return nil
|
return nil
|
||||||
|
@ -301,7 +332,7 @@ func (ps *peerStore) GraduateLeecher(ih bittorrent.InfoHash, p bittorrent.Peer)
|
||||||
|
|
||||||
delete(shard.swarms[ih].leechers, pk)
|
delete(shard.swarms[ih].leechers, pk)
|
||||||
|
|
||||||
shard.swarms[ih].seeders[pk] = time.Now().UnixNano()
|
shard.swarms[ih].seeders[pk] = ps.getClock()
|
||||||
|
|
||||||
shard.Unlock()
|
shard.Unlock()
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Add table
Reference in a new issue