Sergey
Sergey

Reputation: 685

chars per second, KBps, Kilo[bits/bytes] per second, (computer network), how compute right

Sorry for maybe stupid question, but how is really Kbps/... (kilobits per second, and kilobytes per second) is computed? I have such computing now:

DWORD ibytesin=0,ibytes_sttime=0,ibytes_st=0,ibps=0,ilastlen;
DWORD obytesin=0,obytes_sttime=0,obytes_st=0,obps=0,olastlen;

ibytesin - total bytes in for all time;

ibytes_sttime - time when start ibytes_st was assigned;

ibytes_st - bytes count at time of ibytes_sttime;

ibps - kbps/bps/...;

ilastlen - to be more accurate and because my protocol uses request packets, i do not want to take last in length;

The same rules for out traffic (o*).

First harvest for example in bytes:

len = recv(ConnectSocket, (char*)p, readleft, 0);
if(len>0) {
    ibytesin+=len;
    ilastlen=len;
}

Same for out.

Then later in some fast frequently executed place, in stats thread for example:

if ((GetTickCount() - obytes_sttime) >= 1000) // update once per second
{
    obps = (obytesin-obytes_st-olastlen) / 1024 * 8;
    obytes_sttime = GetTickCount();
    obytes_st = obytesin;
    olastlen=0;
}

if ((GetTickCount() - ibytes_sttime) >= 1000) // update once per second
{
    ibps = (ibytesin-ibytes_st-ilastlen) / 1024* 8; // get kilobytes*8 == Kbps ?
    ibytes_sttime = GetTickCount();
    ibytes_st = ibytesin;
    ilastlen=0;
}

sprintf(str, "In/Out %3d / %-3d Kbps/сек", ibps,obps);

I have errorenous speed when i try to increase updates bps shows. For example i want to recalculate it at every 100 msecs, not 1 sec, so as i can imagine i need to divide ibps not by 1024, but by 102 (as 1000/10=100, so 1024/10=102.4), but the speed rate is not computed rightly 100%, it is increased, or i do mistake in my first tryings. How to do right?

Upvotes: 0

Views: 1967

Answers (1)

selbie
selbie

Reputation: 104559

Sergey,

I'm assuming your counters don't have to be accurate to any specific tolerance or standard. And that you just want to have a "running average" displayed periodically. If that's the case, you can use my "Counter" class below which I put together from some previous code that I wrote that counted something else. It just recomputes the "rate" every couple of seconds.

Create an instance of "Counter". After your recv function, call "Increment" with the number of bytes received. Then just call Counter::GetRate whenever you want to print the average. (Divide the result by 1024 and multiply by 8 to convert from "bytes per second" to "kbps".)

You'll notice that the "average N per second" is recomputed every two seconds (instead of every one second). You can change this, but I find that keeping the moving average steady for 2 seconds at a time produces "smoother" results as the counter printout doesn't appear as erratic when there is variance to the count. If you want a count more closer to "how many kbits received in the last second", then call counter.SetInterval(1000). I suppose you could set the interval as low as 100. You'll just get more erratic results due to network jitter.

class Counter
{

    static const DWORD DEFAULT_INTERVAL = 2000; // 2000ms = 2 seconds
    bool m_fFirst;
    DWORD m_dwInterval;  // how often we recompute the average
    DWORD m_dwCount;
    DWORD m_dwStartTime;
    DWORD m_dwComputedRate;

public:
    Counter()
    {
        Reset();
        m_dwInterval = DEFRAULT_INTERVAL;
    }



    void Reset()
    {
        m_dwFrames = 0;
        m_dwStartTime = 0;
        m_dwComputedRate = 0;
        m_fFirst = true;
    }



    void Increment(DWORD dwIncrement)
    {
        DWORD dwCurrentTime = GetTickCount();
        DWORD dwActualInterval = dwCurrentTime - m_dwStartTime;

        if (m_fFirst)
        {
            m_dwStartTime = dwCurrentTime;
            m_fFirst = false;
        }
        else
        {

            m_dwCount += dwIncrement;

            if (dwActualInterval >= m_dwInterval)
            {
                // "round up" by adding 500 to the formula below
                 // that way a computed average of "234.56" gets rounded up to "235" 
                 // instead of "rounded down" to 234
                 const DWORD ROUND_UP = 500;
                 // multiply by 1000 to convert from milliseconds to seconds
                 m_dwComputedRate = (m_dwCount * 1000 + ROUND_UP) / dwActualInterval; 

                 // reset counting
                 m_dwStartTime = dwCurrentTime;
                 m_dwCount = 0;
            }
        }
    }


    // returns rate in terms of "per second"

    DWORD GetRate()
    {
        return m_dwComputedRate;
    }


    void SetInterval(DWORD dwInterval)
    {
        m_dwInterval = dwInterval;
    }
};

Upvotes: 1

Related Questions