libevent中的時間管理 時間快取與校正

2021-08-04 13:39:25 字數 2555 閱讀 1262

上一文章中,知道在libevent中,用了小根堆對timer事件進行管理,其key值對應事件

的超時時間,從小根堆中可以取出最小的超時時間

對於timer,libevnet有乙個時間管理機制,即下面要說到的等待時間管理,時間快取校正等

static int

timeout_next(struct event_base *base, struct timeval **tv_p)

if (gettime(base, &now) == -1)

//如果超時時間<=當前值,不能等待,需要立即返回

if (evutil_timercmp(&ev->ev_timeout, &now, <=))

// 計算等待的時間=當前時間-最小的超時時間

evutil_timersub(&ev->ev_timeout, &now, tv);

return (res);

}

...

//活躍事件總數為0,或flags標誌為0,或evloop阻塞,進行等待時間計算

if (!base->event_count_active && !(flags & evloop_nonblock)) else

res = evsel->dispatch(base, tv_p);

timeout_process(base);//處理超時事件,將超時事件插入到啟用鍊錶中

...

由上可以看出,libevent對timer事件的處理方法就是先計算小根堆最小等待時間是否超時,若超時,將超時的timer事件插入到啟用鍊錶中

對於libevent來講,由於超時操作依賴於時間的準確度,所以每次的操作都要進行時間管理

其主要包括如何獲取時間,當系統時間被更改時如何校正調整,小根堆的調整

2.1 時間的獲取

使用時間快取及更新時間快取的操作

作用:不必每次獲取時間都執行系統呼叫這個相對費時的操作;

/*********gettime 函式裡,獲取快取時間,如果沒有則系統呼叫************/

static

int gettime(struct event_base *base, struct timeval *tp)

...}

在主迴圈中

int event_base_loop(struct event_base *base, int flags)

// 退出時也要清空時間快取

base->tv_cache.tv_sec = 0;

return (0);

}

在標註的時間點 2 到時間點 1 的這段時間(處理就緒事件時),呼叫 gettime()取得的都是

tv_cache 快取的時間

由此使用時間快取,避免了頻繁呼叫系統時間獲取

2.2 時間校正 與 小根堆的調整

monotonic時間類似於uptime,即從開機後算起到當前的時間

函式detect_monotonic()中,檢測到系統支援monotonic時間

就將全域性變數 use_monotonic 設定為 1

如果系統支援monotonic 時間,即所謂的uptime時間,一般不會被更改,則不需要執行校正

要校正的情況:

非monotonic時間,時間被向前調整了

這會造成乙個情況,當前獲取的新時間會小於之前獲取的時間,即

tv_cache(新cache)反而小於event_tv的時間(上次的cache)

調整函式 timeout_correct()完成:

/********evutil.h***/

static

void timeout_correct(struct event_base *base, struct timeval *tv)

evutil_timersub(&base->event_tv, tv, &off);// 計算時間差值

//調整定時事件小根堆

pev = base->timeheap.p;

size = base->timeheap.n;

for (; size-- > 0; ++pev)

base->event_tv = *tv; // 更新event_tv為tv_cache

}

在調整小根堆時,因為所有定時事件的時間值都會被減去相同的值,因此雖然堆中元

素的時間鍵值改變了,但是相對關係並沒有改變,不會改變堆的整體結構。因此只需要遍歷

堆中的所有元素,將每個元素的時間鍵值減去相同的值即可完成調整,不需要重新調整堆的

結構。

當然調整完後,要將 event_tv 值重新設定為 tv_cache 值了

參考:libevent原始碼分析

libevent中的時間管理 小根堆

型別名稱 最小堆 minheap 資料物件集 完全二叉樹,每個結點的元素值不大於其子結點的元素值 最大堆同理可得 是不是堆要注意從根結點到任意結點路徑上結點序列的有序性!另外 關於堆,為了保證陣列第乙個元素就是heap的根節點,heap基本上都是用陣列 或者其他的連續儲存空間 作為其儲存結構的。2....

3 3 8 時間管理

德魯克在 卓有成效的管理者中 寫道 有效的管理者知道,時間是一項限制因素。任何生產程式的產出量,都會受到最稀有資源的制約。在我們稱之為 工作成就 的生產程式裡,最稀有的資源,就是時間。但人們卻往往最不善於管理自己的時間。要提高管理者的有效性,第一步就是記錄其時間耗用的實際情形。第二個步驟就是要做有系...

2021 7 21 時間管理

早上花了乙個小時研究了一下時間管理。1,建立時間概念,意識到時間的價值。具體量化並轉化為金錢,假設我的時薪是1200,每分鐘20塊錢,以此評估做一件事的成本,建立時間的價值觀念。2,時間的利用。時間可分為大塊時間,零碎時間和暗時間。大塊時間做重要的事,盡量避免被打擾,零碎時間做不緊急但重要的事,比如...