Avoid heap allocating new time.Times all the time

This commit is contained in:
Nate Brown 2025-06-20 13:06:02 -05:00
parent 0708bd3202
commit 609c02b591
3 changed files with 24 additions and 22 deletions

View file

@ -107,20 +107,11 @@ func (cm *connectionManager) getInactivityTimeout() time.Duration {
}
func (cm *connectionManager) In(h *HostInfo) {
if h.in.Swap(true) == false {
cm.updateLastCommunication(h)
}
h.in.Store(true)
}
func (cm *connectionManager) Out(h *HostInfo) {
if h.out.Swap(true) == false {
cm.updateLastCommunication(h)
}
}
func (cm *connectionManager) updateLastCommunication(h *HostInfo) {
now := time.Now()
h.lastComms.Store(&now)
h.out.Store(true)
}
func (cm *connectionManager) RelayUsed(localIndex uint32) {
@ -138,9 +129,12 @@ func (cm *connectionManager) RelayUsed(localIndex uint32) {
// getAndResetTrafficCheck returns if there was any inbound or outbound traffic within the last tick and
// resets the state for this local index
func (cm *connectionManager) getAndResetTrafficCheck(h *HostInfo) (bool, bool) {
func (cm *connectionManager) getAndResetTrafficCheck(h *HostInfo, now time.Time) (bool, bool) {
in := h.in.Swap(false)
out := h.out.Swap(false)
if in || out {
h.lastUsed = now
}
return in, out
}
@ -327,7 +321,7 @@ func (cm *connectionManager) makeTrafficDecision(localIndex uint32, now time.Tim
}
// Check for traffic on this hostinfo
inTraffic, outTraffic := cm.getAndResetTrafficCheck(hostinfo)
inTraffic, outTraffic := cm.getAndResetTrafficCheck(hostinfo, now)
// A hostinfo is determined alive if there is incoming traffic
if inTraffic {
@ -424,13 +418,7 @@ func (cm *connectionManager) isInactive(hostinfo *HostInfo, now time.Time) (time
return 0, false
}
lastComm := hostinfo.lastComms.Load()
if lastComm == nil {
// Strangely we don't have any last communication time recorded
return 0, false
}
inactiveDuration := now.Sub(*lastComm)
inactiveDuration := now.Sub(hostinfo.lastUsed)
if inactiveDuration < cm.getInactivityTimeout() {
// It's not considered inactive
return inactiveDuration, false

View file

@ -262,8 +262,16 @@ func Test_NewConnectionManager_DisconnectInactive(t *testing.T) {
assert.True(t, hostinfo.in.Load())
now := time.Now()
decision, _, _ := nc.makeTrafficDecision(hostinfo.localIndexId, now.Add(time.Second*5))
decision, _, _ := nc.makeTrafficDecision(hostinfo.localIndexId, now)
assert.Equal(t, tryRehandshake, decision)
assert.Equal(t, now, hostinfo.lastUsed)
assert.False(t, hostinfo.pendingDeletion.Load())
assert.False(t, hostinfo.out.Load())
assert.False(t, hostinfo.in.Load())
decision, _, _ = nc.makeTrafficDecision(hostinfo.localIndexId, now.Add(time.Second*5))
assert.Equal(t, doNothing, decision)
assert.Equal(t, now, hostinfo.lastUsed)
assert.False(t, hostinfo.pendingDeletion.Load())
assert.False(t, hostinfo.out.Load())
assert.False(t, hostinfo.in.Load())
@ -271,6 +279,7 @@ func Test_NewConnectionManager_DisconnectInactive(t *testing.T) {
// Do another traffic check tick, should still not be pending deletion
decision, _, _ = nc.makeTrafficDecision(hostinfo.localIndexId, now.Add(time.Second*10))
assert.Equal(t, doNothing, decision)
assert.Equal(t, now, hostinfo.lastUsed)
assert.False(t, hostinfo.pendingDeletion.Load())
assert.False(t, hostinfo.out.Load())
assert.False(t, hostinfo.in.Load())
@ -280,6 +289,7 @@ func Test_NewConnectionManager_DisconnectInactive(t *testing.T) {
// Finally advance beyond the inactivity timeout
decision, _, _ = nc.makeTrafficDecision(hostinfo.localIndexId, now.Add(time.Minute*10))
assert.Equal(t, closeTunnel, decision)
assert.Equal(t, now, hostinfo.lastUsed)
assert.False(t, hostinfo.pendingDeletion.Load())
assert.False(t, hostinfo.out.Load())
assert.False(t, hostinfo.in.Load())

View file

@ -245,7 +245,11 @@ type HostInfo struct {
//TODO: in, out, and others might benefit from being an atomic.Int32. We could collapse connectionManager pendingDeletion, relayUsed, and in/out into this 1 thing
in, out, pendingDeletion atomic.Bool
lastComms atomic.Pointer[time.Time]
// lastUsed tracks the last time ConnectionManager checked the tunnel and it was in use.
// This value will be behind against actual tunnel utilization in the hot path.
// This should only be used by the ConnectionManagers ticker routine.
lastUsed time.Time
}
type ViaSender struct {