青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 14,  comments - 57,  trackbacks - 0
  最新?lián)Q了個(gè)項(xiàng)目組,閱讀代碼后,發(fā)現(xiàn)Server端代碼居然沒有事件和定時(shí)器。由于沒有事件,所以各個(gè)模塊代碼互相調(diào)用的地方特別多,導(dǎo)致代碼結(jié)構(gòu)混亂,所有代碼都放在一塊,亂成一鍋粥了。
沒有定時(shí)器,所有需要定時(shí)的任務(wù),都只能添加類似OnUpdate的函數(shù),在主循環(huán)的時(shí)候執(zhí)行。定時(shí)需求少的時(shí)候,看不出明顯的問題,但是一旦這種需求多了,尤其是很多內(nèi)部對象有定時(shí)需求的時(shí)候,
這個(gè)問題就比較明顯了,寫好了OnUpdate后,還要建立一條從主循環(huán)MainLoop到自身OnUpdate的調(diào)用鏈。
 
  事件其實(shí)就是一個(gè)廣播和訂閱的關(guān)系,Delegate就是實(shí)現(xiàn)這樣一套機(jī)制的利器,目前Delegate的實(shí)現(xiàn)主要有2種,一種是CodeProject上的一個(gè)FastDelegate實(shí)現(xiàn),另外一個(gè)比較典型的實(shí)現(xiàn)就是boost的
實(shí)現(xiàn)了,無論采取哪種實(shí)現(xiàn)方案,實(shí)現(xiàn)難度都不算太大。
  Server當(dāng)前框架對定時(shí)器無任何支持,只有一個(gè)DoMainLoop的函數(shù)可以派生來運(yùn)行自己的定時(shí)邏輯。
  我原來都是用的ACE封裝的組件,用了一段時(shí)間也沒發(fā)現(xiàn)明顯問題,不過ACE的定時(shí)器不太適合在這個(gè)新項(xiàng)目用,主要原因有如下幾點(diǎn):
  1、ACE庫太大了,不想僅僅為了定時(shí)器引入一個(gè)這么龐大的庫。
  2、ACE的定時(shí)器需要額外啟動(dòng)一個(gè)定時(shí)器線程,定時(shí)任務(wù)是在定時(shí)器線程跑的,而我們的項(xiàng)目邏輯其實(shí)是在單個(gè)線程運(yùn)行的,如果直接采用ACE定時(shí)器,會給邏輯帶來額外的復(fù)雜度。由于整個(gè)邏輯線程的框架是公共模塊,手頭也沒有代碼,所以將定時(shí)器線程的任務(wù)發(fā)送到主邏輯線程運(yùn)行也是不可行的。
  3、ACE的定時(shí)器有很多種,TIMER_QUEUE、TIMER_WHELL、TIMER_HEAP等,個(gè)人感覺這些定時(shí)器的插入、取消操作都比較耗時(shí),加以改裝放到主線程run的帶價(jià)將會很大。

其實(shí)linux內(nèi)核就有一個(gè)比較高性能的定時(shí)器,代碼在kernel/Timer.c里, 2.6內(nèi)核的定時(shí)器代碼更是簡潔。
linux的定時(shí)任務(wù)都是以jiffie 為單位的,linux將所有定時(shí)任務(wù)分為5個(gè)階梯,
struct tvec {
    struct list_head vec[TVN_SIZE];
};

struct tvec_root {
    struct list_head vec[TVR_SIZE];
};

struct tvec_base {
    spinlock_t lock;
    struct timer_list *running_timer;
    unsigned long timer_jiffies;
    struct tvec_root tv1;
    struct tvec tv2;
    struct tvec tv3;
    struct tvec tv4;
    struct tvec tv5;
} ____cacheline_aligned;

對一個(gè)新的定時(shí)任務(wù),處理方法如下:
static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
{
    unsigned long expires = timer->expires;
    unsigned long idx = expires - base->timer_jiffies;
    struct list_head *vec;

    if (idx < TVR_SIZE) {
        int i = expires & TVR_MASK;
        vec = base->tv1.vec + i;
    } else if (idx < 1 << (TVR_BITS + TVN_BITS)) {
        int i = (expires >> TVR_BITS) & TVN_MASK;
        vec = base->tv2.vec + i;
    } else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {
        int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
        vec = base->tv3.vec + i;
    } else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {
        int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
        vec = base->tv4.vec + i;
    } else if ((signed long) idx < 0) {
        /*
         * Can happen if you add a timer with expires == jiffies,
         * or you set a timer to go off in the past
         */
        vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
    } else {
        int i;
        /* If the timeout is larger than 0xffffffff on 64-bit
         * architectures then we use the maximum timeout:
         */
        if (idx > 0xffffffffUL) {
            idx = 0xffffffffUL;
            expires = idx + base->timer_jiffies;
        }
        i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
        vec = base->tv5.vec + i;
    }
    /*
     * Timers are FIFO:
     */
    list_add_tail(&timer->entry, vec);
}
從上可以看到Linux對定時(shí)器的處理:對即將在TVR_SIZE 個(gè)jiffies內(nèi)到達(dá)的定時(shí)任務(wù),將它掛到第一組tv1 下,具體就是掛到expires & TVR_MASK 對應(yīng)的列表上去。
同一個(gè)jiffies到達(dá)的定時(shí)器是掛在同一個(gè)鏈表的。
同理,掛到第二個(gè)組的是 到期時(shí)間小于 1 << (TVR_BITS + TVN_BITS) jiffies的。
掛到第三個(gè)組的是 到期時(shí)間小于1 << (TVR_BITS + 2 * TVN_BITS) jiffies的。
掛到第四個(gè)組的是 到期時(shí)間小于 1 << (TVR_BITS + 3 * TVN_BITS) jiffies的。
超過1 << (TVR_BITS + 3 * TVN_BITS) 的掛到第五組。
這樣,所有到期的任務(wù)都會在第一組。任何時(shí)刻都可以直接通過當(dāng)前jiffies&TVR_SIZE 來找到需要運(yùn)行的定時(shí)器任務(wù)列表,定時(shí)器的插入效率就是O(1)。

下面是定時(shí)器的運(yùn)行代碼:
static int cascade(struct tvec_base *base, struct tvec *tv, int index)
{
    /* cascade all the timers from tv up one level */
    struct timer_list *timer, *tmp;
    struct list_head tv_list;

    list_replace_init(tv->vec + index, &tv_list);

    /*
     * We are removing _all_ timers from the list, so we
     * don't have to detach them individually.
     */
    list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
        BUG_ON(tbase_get_base(timer->base) != base);
        internal_add_timer(base, timer);
    }

    return index;
}

#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)

/**
 * __run_timers - run all expired timers (if any) on this CPU.
 * @base: the timer vector to be processed.
 *
 * This function cascades all vectors and executes all expired timer
 * vectors.
 */
static inline void __run_timers(struct tvec_base *base)
{
    struct timer_list *timer;

    spin_lock_irq(&base->lock);
    while (time_after_eq(jiffies, base->timer_jiffies)) {
        struct list_head work_list;
        struct list_head *head = &work_list;
        int index = base->timer_jiffies & TVR_MASK;

        /*
         * Cascade timers:
         */
        if (!index &&
            (!cascade(base, &base->tv2, INDEX(0))) &&
                (!cascade(base, &base->tv3, INDEX(1))) &&
                    !cascade(base, &base->tv4, INDEX(2)))
            cascade(base, &base->tv5, INDEX(3));
        ++base->timer_jiffies;
        list_replace_init(base->tv1.vec + index, &work_list);
        while (!list_empty(head)) {
            void (*fn)(unsigned long);
            unsigned long data;

            timer = list_first_entry(head, struct timer_list,entry);
            fn = timer->function;
            data = timer->data;

            timer_stats_account_timer(timer);

            set_running_timer(base, timer);
            detach_timer(timer, 1);
            spin_unlock_irq(&base->lock);
            {
                int preempt_count = preempt_count();
                fn(data);
                if (preempt_count != preempt_count()) {
                    printk(KERN_ERR "huh, entered %p "
                           "with preempt_count %08x, exited"
                           " with %08x?\n",
                           fn, preempt_count,
                           preempt_count());
                    BUG();
                }
            }
            spin_lock_irq(&base->lock);
        }
    }
    set_running_timer(base, NULL);
    spin_unlock_irq(&base->lock);
}
當(dāng)?shù)谝唤M運(yùn)行完一輪后,需要將tv2的一組新的定時(shí)任務(wù)加到第一組。這就好比時(shí)鐘的指針,秒針運(yùn)行一圈后,分針步進(jìn)一格,后續(xù)的調(diào)整都是類似。
cascade 就是負(fù)責(zé)將下一組的定時(shí)任務(wù)添加到前面的任務(wù)階梯。只有當(dāng)?shù)谝惠喌亩〞r(shí)任務(wù)全部運(yùn)行完畢后,才會需要從第二輪調(diào)入新的任務(wù),只有第二級別的任務(wù)都調(diào)入完畢后,才需要從第三輪的定時(shí)任務(wù)調(diào)入新的任務(wù):
 if (!index &&
            (!cascade(base, &base->tv2, INDEX(0))) &&
                (!cascade(base, &base->tv3, INDEX(1))) &&
                    !cascade(base, &base->tv4, INDEX(2)))
            cascade(base, &base->tv5, INDEX(3));

這就是負(fù)責(zé)調(diào)整的代碼,相當(dāng)?shù)暮啙崱?br>參照上述代碼實(shí)現(xiàn)一個(gè)定時(shí)器后,加入4000個(gè)定時(shí)任務(wù):
    for(int i = 1; i < 4000; i++)
    {
        g_TimerHandle[i] = g_timerManager.setTimer(&tmpSink1, i, i*10, "ss");
    }
從10毫秒到4000*10毫秒,運(yùn)行后,測試下性能,
函數(shù)名                                    執(zhí)行次數(shù)    最小時(shí)間     平均時(shí)間       最大時(shí)間
TimerManager::runTimer    2170566        10              10               3046   
可以看到,除了個(gè)別時(shí)間是因?yàn)榫€程切換導(dǎo)致數(shù)據(jù)比較大外,平均每次運(yùn)行runTimer的時(shí)間是10微秒。
這個(gè)時(shí)間還包括每個(gè)定時(shí)器的執(zhí)行消耗,效率還是不錯(cuò)的。
posted on 2011-03-13 22:06 feixuwu 閱讀(2115) 評論(0)  編輯 收藏 引用 所屬分類: 游戲開發(fā)
<2011年3月>
272812345
6789101112
13141516171819
20212223242526
272829303112
3456789

文章轉(zhuǎn)載請注明出處

常用鏈接

留言簿(11)

隨筆分類

隨筆檔案

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            午夜精品福利一区二区三区av| 牛牛影视久久网| 亚洲靠逼com| 欧美一区二区在线免费观看 | 在线看视频不卡| 一区二区三区国产盗摄| 一区精品在线播放| 亚洲综合久久久久| 亚洲一区二区高清视频| 欧美大片在线观看一区| 久久视频在线看| 国产精品乱码妇女bbbb| 亚洲区在线播放| 国产视频在线观看一区二区| av不卡在线| 在线视频欧美日韩精品| 欧美成人亚洲| 欧美激情欧美狂野欧美精品| 1769国内精品视频在线播放| 校园春色国产精品| 久久精品国产视频| 国产欧美日韩一区二区三区在线| 亚洲一二三区视频在线观看| 亚洲深夜福利在线| 欧美日韩激情小视频| 亚洲乱码视频| 正在播放日韩| 欧美性片在线观看| 亚洲视频在线观看免费| 午夜精品亚洲| 国产欧美一区二区色老头| 亚洲伊人一本大道中文字幕| 欧美亚洲色图校园春色| 国产精品欧美在线| 欧美亚洲尤物久久| 久久亚洲综合色| 亚洲电影免费观看高清| 农村妇女精品| 日韩一级黄色大片| 亚洲欧美日韩国产一区二区三区| 国产精品任我爽爆在线播放| 午夜欧美理论片| 免费永久网站黄欧美| 亚洲三级观看| 国产精品蜜臀在线观看| 性娇小13――14欧美| 女人香蕉久久**毛片精品| 亚洲欧洲日本专区| 欧美吻胸吃奶大尺度电影| 午夜精品婷婷| 欧美成人免费全部| 在线一区二区三区做爰视频网站| 国产精品网站在线| 久久免费视频网| 亚洲精品小视频| 欧美综合国产| 亚洲精品久久| 国产精品理论片| 久久夜色精品国产| 99国产一区| 久久人人超碰| 中文国产成人精品| 黄网动漫久久久| 欧美日韩一区三区四区| 久久激情综合| 一区二区三区日韩在线观看| 久久久久久久久久久久久女国产乱 | 欧美高清免费| 欧美亚洲日本网站| 亚洲激情偷拍| 久久精品亚洲一区二区三区浴池| 亚洲欧洲三级| 国产在线日韩| 国产精品久久福利| 美女999久久久精品视频| 亚洲天堂久久| 亚洲欧洲精品成人久久奇米网 | 久久精品国产一区二区三| 亚洲精品资源| 欧美国产高清| 久久国产精品亚洲77777| 一本大道久久精品懂色aⅴ| 国一区二区在线观看| 国产精品videosex极品| 欧美fxxxxxx另类| 久久都是精品| 亚洲欧美视频在线| 99精品热视频| 亚洲国产日本| 欧美成人国产一区二区| 亚洲欧美日韩在线不卡| 一区二区三区成人| 最近看过的日韩成人| 黑人一区二区| 国产一区亚洲一区| 国产情侣久久| 国产欧美精品一区二区三区介绍| 欧美网站在线观看| 欧美日韩性生活视频| 欧美精品一区二区三区一线天视频| 久久一区亚洲| 久久综合伊人77777麻豆| 久久久国产精品一区| 欧美亚洲一区| 欧美专区亚洲专区| 欧美在线视频网站| 久久疯狂做爰流白浆xx| 欧美一区二区观看视频| 欧美在线视频a| 久久九九热免费视频| 久久嫩草精品久久久精品一| 久久精品国产第一区二区三区最新章节 | 亚洲黄色高清| 亚洲人成啪啪网站| 亚洲美女视频网| av不卡在线看| 亚洲午夜精品一区二区| 亚洲午夜精品网| 欧美中在线观看| 久久精品盗摄| 麻豆免费精品视频| 亚洲大片av| 亚洲人午夜精品| 亚洲一本大道在线| 久久精品久久综合| 欧美福利电影网| 欧美私人啪啪vps| 国产免费成人| 亚洲国产精品美女| 一本色道久久综合亚洲精品不卡 | 99这里有精品| 性欧美激情精品| 看欧美日韩国产| 91久久黄色| 亚洲在线观看免费| 久久久久综合一区二区三区| 欧美国产视频在线| 国产精品日韩欧美大师| 尤物99国产成人精品视频| 日韩视频在线观看国产| 先锋影音国产精品| 嫩草国产精品入口| 一区二区日本视频| 久久九九有精品国产23| 欧美日韩三区| 黄色日韩在线| 亚洲图中文字幕| 麻豆精品精品国产自在97香蕉| 亚洲人成网站777色婷婷| 午夜精品久久久久久久99樱桃 | 欧美中文在线字幕| 亚洲日本激情| 久久久久国产精品www| 欧美日韩亚洲三区| 亚洲电影在线播放| 亚洲欧美一区二区三区在线| 欧美激情 亚洲a∨综合| 亚洲在线视频观看| 欧美精品不卡| 激情五月***国产精品| 亚洲欧美精品| 91久久精品日日躁夜夜躁欧美 | 亚洲一区二区三区视频播放| 女仆av观看一区| 国产一区二区主播在线| 亚洲欧美国产不卡| 亚洲国产免费| 久久视频精品在线| 国产午夜精品视频| 亚洲综合日韩中文字幕v在线| 欧美激情一区二区三区成人| 欧美一区二区成人6969| 国产免费亚洲高清| 亚洲一级二级在线| 亚洲欧洲另类国产综合| 久久深夜福利| 经典三级久久| 久久久久网址| 欧美一区二区免费观在线| 欧美三级中文字幕在线观看| 亚洲日本中文字幕免费在线不卡| 毛片一区二区| 久久精品人人做人人爽| 国产视频自拍一区| 久久国产精品亚洲va麻豆| 亚洲一区日韩| 国产精品欧美在线| 性色av一区二区三区在线观看| 99国产精品99久久久久久粉嫩| 欧美国产视频一区二区| 99亚洲视频| 日韩亚洲欧美一区| 欧美三级免费| 亚洲欧美日韩国产中文| 亚洲一区视频| 国产日韩av高清| 久久色在线播放| 久久影视三级福利片| 亚洲国产精品一区二区www在线| 欧美高清hd18日本|