📄 rate.cpp
字号:
#include <sys/time.h>#include "rate.h"#include "bufio.h" // for BUF_DEF_SIZ#include "bttime.h"#include "console.h"#define RATE_INTERVAL 20#define SHORT_INTERVAL 5Rate::Rate(){ m_last_timestamp = m_total_timeused = (time_t)0; m_count_bytes = 0; m_history = m_history_last = (BWSAMPLE *)0; m_last_realtime = m_recent_realtime = m_prev_realtime = 0; m_last_size = m_recent_size = m_prev_size = 0; m_selfrate = (Rate *)0; m_late = 0; m_ontime = 0;}void Rate::Reset(){ m_last_timestamp = m_total_timeused = (time_t)0; ClearHistory(); m_last_realtime = 0; m_last_size = 0;}void Rate::StartTimer(){ if( !m_last_timestamp ) m_last_timestamp = now;}void Rate::StopTimer(){ if( m_last_timestamp ){ m_total_timeused += (now - m_last_timestamp); m_last_timestamp = 0; ClearHistory(); }}BWSAMPLE *Rate::NewSample(){ BWSAMPLE *sample = new BWSAMPLE; if( sample ){ sample->timestamp = 0; sample->bytes = 0; sample->next = (BWSAMPLE *)0; }else CONSOLE.Warning(2, "warn, failed to allocate memory for bandwidth sample."); return sample;}void Rate::ClearHistory(){ if( m_history ){ BWSAMPLE *pnext; for( BWSAMPLE *p=m_history; p; p=pnext ){ pnext = p->next; delete p; } m_history = m_history_last = (BWSAMPLE *)0; }}void Rate::Cleanup(){ BWSAMPLE *p = m_history; while( p && RATE_INTERVAL <= now - (time_t)(p->timestamp) ){ int nzero = 0; if( !p->next ){ if( BWSAMPLE *q = NewSample() ){ q->timestamp = (double)now - 1; p->next = q; m_history_last = q; nzero++; }else{ p->bytes = p->bytes * RATE_INTERVAL / (now - (time_t)(p->timestamp)); p->timestamp = (double)(now - RATE_INTERVAL + 1); } } if( p->next ){ if( RATE_INTERVAL > now - (time_t)(p->next->timestamp) ){ time_t reftime = nzero ? now : (time_t)(p->next->timestamp); while( (time_t)(p->next->timestamp) > (time_t)(p->timestamp) + 1 ){ // fill holes if( BWSAMPLE *q = NewSample() ){ q->timestamp = (double)((time_t)(p->next->timestamp) - 1); q->next = p->next; p->next = q; nzero++; }else break; } if( nzero ){ size_t bytes = (size_t)( p->bytes / (reftime - p->timestamp) ); BWSAMPLE *q = p->next; for( ; nzero; nzero-- ){ q->bytes += bytes; // distribute over the following empty samples q = q->next; } } } m_history = p->next; delete p; p = m_history; } }}void Rate::CountAdd(size_t nbytes){ m_count_bytes += nbytes; if( m_selfrate ) m_selfrate->CountAdd(nbytes);}void Rate::RateAdd(size_t nbytes, size_t bwlimit){ struct timespec nowspec; clock_gettime(CLOCK_REALTIME, &nowspec); RateAdd(nbytes, bwlimit, nowspec.tv_sec + (double)(nowspec.tv_nsec)/1000000000);}void Rate::RateAdd(size_t nbytes, size_t bwlimit, double timestamp){ if( m_history_last && timestamp < m_history_last->timestamp ){ // time went backward ClearHistory(); }else Cleanup(); if( timestamp <= m_last_realtime ){ // time went backward m_ontime = 0; m_last_size = 0; m_last_realtime = 0; } if( m_history_last && (time_t)timestamp == (time_t)(m_history_last->timestamp) ) m_history_last->bytes += nbytes; else{ if( BWSAMPLE *p = NewSample() ){ p->timestamp = timestamp; p->bytes = nbytes; if( m_history_last ) m_history_last->next = p; else m_history = p; m_history_last = p; } } if( !m_selfrate && m_ontime ){ double late=timestamp - (m_last_realtime + (double)m_last_size / bwlimit); // keep the change under control in case the system gets weird on us if( late < 0 ) late /= 2; else if( m_late && late > m_late ) late = m_late / 2; m_late += late; m_ontime = 0; } if( m_selfrate && bwlimit && m_last_realtime && m_selfrate->LastSize() / (timestamp - m_selfrate->LastRealtime()) > bwlimit ) m_last_size += nbytes; else if( !m_selfrate && bwlimit && m_last_realtime && m_last_size / (timestamp - m_last_realtime) > bwlimit ) m_last_size += nbytes; else{ m_last_realtime = timestamp; m_last_size = nbytes; } if( nbytes > BUF_DEF_SIZ ){ m_prev_realtime = m_recent_realtime; m_prev_size = m_recent_size; m_recent_realtime = timestamp; m_recent_size = nbytes; }else m_recent_size += nbytes; if( m_selfrate ) m_selfrate->RateAdd(nbytes, bwlimit, timestamp);}void Rate::operator=(const Rate &ra){ m_last_timestamp = now; m_count_bytes = ra.m_count_bytes;}size_t Rate::CurrentRate(){ // We can't make up for past slowness by overloading the line now/future. // Look at only the most recent data sent/received. if( !m_last_timestamp || !m_history ) return 0; // no current rate struct timespec timestamp; clock_gettime(CLOCK_REALTIME, ×tamp); double timeused = timestamp.tv_sec + (double)(timestamp.tv_nsec)/1000000000 - m_last_realtime; if( timeused <= 0 ) return 0; return (size_t)( m_last_size / timeused );}size_t Rate::RateMeasure(){ // calculate rate based on bandwidth history data time_t timestamp = now; uint64_t countbytes = 0; double timeused = 0; BWSAMPLE *p; if( !m_last_timestamp || !m_history ) return 0; // no current rate Cleanup(); for( p=m_history; p; p=p->next ){ countbytes += p->bytes; } timeused = (double)(now - (time_t)(m_history->timestamp)); if( timeused == 0 ) timeused = 1; else if( timeused < 0 ) ClearHistory(); // time went backward if( now < (time_t)m_recent_realtime ){ if( m_history ){ m_recent_realtime = (double)now; m_prev_realtime = (double)(now - 1); m_recent_size = m_prev_size = 0; }else{ m_recent_realtime = m_prev_realtime = 0; m_recent_size = m_prev_size = 0; } } if( !m_history ) return 0; // Don't let the most recent addition inflate the rate measurement. if( now == (time_t)m_recent_realtime ){ // don't count the most recent addition countbytes -= m_recent_size; timeused = m_recent_realtime - m_history->timestamp; }else if( m_recent_realtime && RATE_INTERVAL > now - (time_t)m_recent_realtime && m_recent_size / (now - (time_t)m_recent_realtime) > m_prev_size / (m_recent_realtime - m_prev_realtime) ){ // "tone down" the most recent to match the previous addition's rate countbytes -= m_recent_size; countbytes += (uint64_t)( m_prev_size / (m_recent_realtime - m_prev_realtime) * (now - (time_t)m_recent_realtime) ); } return (size_t)(countbytes / timeused);}size_t Rate::RateMeasure(const Rate &ra_to){ time_t timeused = TimeUsed(); int tmp = ra_to.m_count_bytes - m_count_bytes; return (size_t)( (tmp>0) ? (tmp/(timeused ? timeused : 1)) : 0 );}time_t Rate::TimeUsed(){ if( now < m_last_timestamp ) m_last_timestamp = now; return now - m_last_timestamp;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -