mirror of
https://github.com/xtaci/kcp-go.git
synced 2026-10-20 08:16:39 +00:00
Optimizations: - ringbuffer: optimize Len(), IsEmpty(), Discard(), Clear() methods with branchless arithmetic and simplified logic - fec: fix memory leak in shardHeap.Pop() by setting element to nil before truncating slice, preventing GC from holding stale references - timedsched: fix memory leak in timedFuncHeap.Pop() with same nil-before-truncate pattern; optimize prepend() using slice swap instead of append - autotune: add sortCache field to Autotuner to reuse slice allocation in FindPeriod(), avoiding repeated allocations during period detection - snmp: replace fmt.Sprint with strconv.FormatUint for better performance in Copy() and Reset() methods - entropy: remove defer overhead in rngAES.Read() and rngChacha8.Read() hot paths for reduced function call cost - bufferpool: pre-allocate ErrBufferPoolSizeExceeded error; reset slice length on Put() to allow proper reuse - sess: remove defer overhead in 6 setter methods (SetWriteDelay, SetWindowSize, SetStreamMode, SetACKNoDelay, SetDUP, SetNoDelay) These changes reduce memory allocations, fix potential memory leaks in heap-based data structures, and eliminate defer overhead in frequently called methods.
217 lines
8.0 KiB
Go
217 lines
8.0 KiB
Go
// The MIT License (MIT)
|
|
//
|
|
// Copyright (c) 2015 xtaci
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
|
|
package kcp
|
|
|
|
import (
|
|
"strconv"
|
|
"sync/atomic"
|
|
)
|
|
|
|
// Snmp defines network statistics indicator
|
|
type Snmp struct {
|
|
BytesSent uint64 // bytes sent from upper level
|
|
BytesReceived uint64 // bytes received to upper level
|
|
MaxConn uint64 // max number of connections ever reached
|
|
ActiveOpens uint64 // accumulated active open connections
|
|
PassiveOpens uint64 // accumulated passive open connections
|
|
CurrEstab uint64 // current number of established connections
|
|
InErrs uint64 // UDP read errors reported from net.PacketConn
|
|
InCsumErrors uint64 // checksum errors from CRC32
|
|
KCPInErrors uint64 // packet iput errors reported from KCP
|
|
InPkts uint64 // incoming packets count
|
|
OutPkts uint64 // outgoing packets count
|
|
InSegs uint64 // incoming KCP segments
|
|
OutSegs uint64 // outgoing KCP segments
|
|
InBytes uint64 // UDP bytes received
|
|
OutBytes uint64 // UDP bytes sent
|
|
RetransSegs uint64 // accmulated retransmited segments
|
|
FastRetransSegs uint64 // accmulated fast retransmitted segments
|
|
EarlyRetransSegs uint64 // accmulated early retransmitted segments
|
|
LostSegs uint64 // number of segs inferred as lost
|
|
RepeatSegs uint64 // number of segs duplicated
|
|
FECFullShardSet uint64 // number of FEC segments that are full
|
|
FECRecovered uint64 // correct packets recovered from FEC
|
|
FECErrs uint64 // incorrect packets recovered from FEC
|
|
FECParityShards uint64 // FEC segments received
|
|
FECShardSet uint64 // number of parity shards that are not yet received
|
|
FECShardMin uint64 // the minimum ID of FEC shards
|
|
RingBufferSndQueue uint64 // Len of segments in send queue ring buffer
|
|
RingBufferRcvQueue uint64 // Len of segments in receive queue ring buffer
|
|
RingBufferSndBuffer uint64 // Len of segments in send buffer ring buffer
|
|
OOBPackets uint64 // number of OOB packets received
|
|
}
|
|
|
|
func newSnmp() *Snmp {
|
|
return new(Snmp)
|
|
}
|
|
|
|
// Header returns all field names
|
|
func (s *Snmp) Header() []string {
|
|
return []string{
|
|
"BytesSent",
|
|
"BytesReceived",
|
|
"MaxConn",
|
|
"ActiveOpens",
|
|
"PassiveOpens",
|
|
"CurrEstab",
|
|
"InErrs",
|
|
"InCsumErrors",
|
|
"KCPInErrors",
|
|
"InPkts",
|
|
"OutPkts",
|
|
"InSegs",
|
|
"OutSegs",
|
|
"InBytes",
|
|
"OutBytes",
|
|
"RetransSegs",
|
|
"FastRetransSegs",
|
|
"EarlyRetransSegs",
|
|
"LostSegs",
|
|
"RepeatSegs",
|
|
"FECFullShards",
|
|
"FECParityShards",
|
|
"FECErrs",
|
|
"FECRecovered",
|
|
"FECShardSet",
|
|
"FECShardMin",
|
|
"RingBufferSndQueue",
|
|
"RingBufferRcvQueue",
|
|
"RingBufferSndBuffer",
|
|
"OOBPackets",
|
|
}
|
|
}
|
|
|
|
// ToSlice returns current snmp info as slice
|
|
func (s *Snmp) ToSlice() []string {
|
|
snmp := s.Copy()
|
|
return []string{
|
|
strconv.FormatUint(snmp.BytesSent, 10),
|
|
strconv.FormatUint(snmp.BytesReceived, 10),
|
|
strconv.FormatUint(snmp.MaxConn, 10),
|
|
strconv.FormatUint(snmp.ActiveOpens, 10),
|
|
strconv.FormatUint(snmp.PassiveOpens, 10),
|
|
strconv.FormatUint(snmp.CurrEstab, 10),
|
|
strconv.FormatUint(snmp.InErrs, 10),
|
|
strconv.FormatUint(snmp.InCsumErrors, 10),
|
|
strconv.FormatUint(snmp.KCPInErrors, 10),
|
|
strconv.FormatUint(snmp.InPkts, 10),
|
|
strconv.FormatUint(snmp.OutPkts, 10),
|
|
strconv.FormatUint(snmp.InSegs, 10),
|
|
strconv.FormatUint(snmp.OutSegs, 10),
|
|
strconv.FormatUint(snmp.InBytes, 10),
|
|
strconv.FormatUint(snmp.OutBytes, 10),
|
|
strconv.FormatUint(snmp.RetransSegs, 10),
|
|
strconv.FormatUint(snmp.FastRetransSegs, 10),
|
|
strconv.FormatUint(snmp.EarlyRetransSegs, 10),
|
|
strconv.FormatUint(snmp.LostSegs, 10),
|
|
strconv.FormatUint(snmp.RepeatSegs, 10),
|
|
strconv.FormatUint(snmp.FECFullShardSet, 10),
|
|
strconv.FormatUint(snmp.FECParityShards, 10),
|
|
strconv.FormatUint(snmp.FECErrs, 10),
|
|
strconv.FormatUint(snmp.FECRecovered, 10),
|
|
strconv.FormatUint(snmp.FECShardSet, 10),
|
|
strconv.FormatUint(snmp.FECShardMin, 10),
|
|
strconv.FormatUint(snmp.RingBufferSndQueue, 10),
|
|
strconv.FormatUint(snmp.RingBufferRcvQueue, 10),
|
|
strconv.FormatUint(snmp.RingBufferSndBuffer, 10),
|
|
strconv.FormatUint(snmp.OOBPackets, 10),
|
|
}
|
|
}
|
|
|
|
// Copy make a copy of current snmp snapshot
|
|
func (s *Snmp) Copy() *Snmp {
|
|
d := newSnmp()
|
|
d.BytesSent = atomic.LoadUint64(&s.BytesSent)
|
|
d.BytesReceived = atomic.LoadUint64(&s.BytesReceived)
|
|
d.MaxConn = atomic.LoadUint64(&s.MaxConn)
|
|
d.ActiveOpens = atomic.LoadUint64(&s.ActiveOpens)
|
|
d.PassiveOpens = atomic.LoadUint64(&s.PassiveOpens)
|
|
d.CurrEstab = atomic.LoadUint64(&s.CurrEstab)
|
|
d.InErrs = atomic.LoadUint64(&s.InErrs)
|
|
d.InCsumErrors = atomic.LoadUint64(&s.InCsumErrors)
|
|
d.KCPInErrors = atomic.LoadUint64(&s.KCPInErrors)
|
|
d.InPkts = atomic.LoadUint64(&s.InPkts)
|
|
d.OutPkts = atomic.LoadUint64(&s.OutPkts)
|
|
d.InSegs = atomic.LoadUint64(&s.InSegs)
|
|
d.OutSegs = atomic.LoadUint64(&s.OutSegs)
|
|
d.InBytes = atomic.LoadUint64(&s.InBytes)
|
|
d.OutBytes = atomic.LoadUint64(&s.OutBytes)
|
|
d.RetransSegs = atomic.LoadUint64(&s.RetransSegs)
|
|
d.FastRetransSegs = atomic.LoadUint64(&s.FastRetransSegs)
|
|
d.EarlyRetransSegs = atomic.LoadUint64(&s.EarlyRetransSegs)
|
|
d.LostSegs = atomic.LoadUint64(&s.LostSegs)
|
|
d.RepeatSegs = atomic.LoadUint64(&s.RepeatSegs)
|
|
d.FECFullShardSet = atomic.LoadUint64(&s.FECFullShardSet)
|
|
d.FECParityShards = atomic.LoadUint64(&s.FECParityShards)
|
|
d.FECErrs = atomic.LoadUint64(&s.FECErrs)
|
|
d.FECRecovered = atomic.LoadUint64(&s.FECRecovered)
|
|
d.FECShardSet = atomic.LoadUint64(&s.FECShardSet)
|
|
d.FECShardMin = atomic.LoadUint64(&s.FECShardMin)
|
|
d.RingBufferSndQueue = atomic.LoadUint64(&s.RingBufferSndQueue)
|
|
d.RingBufferRcvQueue = atomic.LoadUint64(&s.RingBufferRcvQueue)
|
|
d.RingBufferSndBuffer = atomic.LoadUint64(&s.RingBufferSndBuffer)
|
|
d.OOBPackets = atomic.LoadUint64(&s.OOBPackets)
|
|
return d
|
|
}
|
|
|
|
// Reset values to zero
|
|
func (s *Snmp) Reset() {
|
|
atomic.StoreUint64(&s.BytesSent, 0)
|
|
atomic.StoreUint64(&s.BytesReceived, 0)
|
|
atomic.StoreUint64(&s.MaxConn, 0)
|
|
atomic.StoreUint64(&s.ActiveOpens, 0)
|
|
atomic.StoreUint64(&s.PassiveOpens, 0)
|
|
atomic.StoreUint64(&s.CurrEstab, 0)
|
|
atomic.StoreUint64(&s.InErrs, 0)
|
|
atomic.StoreUint64(&s.InCsumErrors, 0)
|
|
atomic.StoreUint64(&s.KCPInErrors, 0)
|
|
atomic.StoreUint64(&s.InPkts, 0)
|
|
atomic.StoreUint64(&s.OutPkts, 0)
|
|
atomic.StoreUint64(&s.InSegs, 0)
|
|
atomic.StoreUint64(&s.OutSegs, 0)
|
|
atomic.StoreUint64(&s.InBytes, 0)
|
|
atomic.StoreUint64(&s.OutBytes, 0)
|
|
atomic.StoreUint64(&s.RetransSegs, 0)
|
|
atomic.StoreUint64(&s.FastRetransSegs, 0)
|
|
atomic.StoreUint64(&s.EarlyRetransSegs, 0)
|
|
atomic.StoreUint64(&s.LostSegs, 0)
|
|
atomic.StoreUint64(&s.RepeatSegs, 0)
|
|
atomic.StoreUint64(&s.FECFullShardSet, 0)
|
|
atomic.StoreUint64(&s.FECParityShards, 0)
|
|
atomic.StoreUint64(&s.FECErrs, 0)
|
|
atomic.StoreUint64(&s.FECRecovered, 0)
|
|
atomic.StoreUint64(&s.FECShardSet, 0)
|
|
atomic.StoreUint64(&s.FECShardMin, 0)
|
|
atomic.StoreUint64(&s.RingBufferSndQueue, 0)
|
|
atomic.StoreUint64(&s.RingBufferRcvQueue, 0)
|
|
atomic.StoreUint64(&s.RingBufferSndBuffer, 0)
|
|
atomic.StoreUint64(&s.OOBPackets, 0)
|
|
}
|
|
|
|
// DefaultSnmp is the global KCP connection statistics collector
|
|
var DefaultSnmp *Snmp
|
|
|
|
func init() {
|
|
DefaultSnmp = newSnmp()
|
|
}
|