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

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

其實linux內核就有一個比較高性能的定時器,代碼在kernel/Timer.c里, 2.6內核的定時器代碼更是簡潔。
linux的定時任務都是以jiffie 為單位的,linux將所有定時任務分為5個階梯,
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;

對一個新的定時任務,處理方法如下:
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對定時器的處理:對即將在TVR_SIZE 個jiffies內到達的定時任務,將它掛到第一組tv1 下,具體就是掛到expires & TVR_MASK 對應的列表上去。
同一個jiffies到達的定時器是掛在同一個鏈表的。
同理,掛到第二個組的是 到期時間小于 1 << (TVR_BITS + TVN_BITS) jiffies的。
掛到第三個組的是 到期時間小于1 << (TVR_BITS + 2 * TVN_BITS) jiffies的。
掛到第四個組的是 到期時間小于 1 << (TVR_BITS + 3 * TVN_BITS) jiffies的。
超過1 << (TVR_BITS + 3 * TVN_BITS) 的掛到第五組。
這樣,所有到期的任務都會在第一組。任何時刻都可以直接通過當前jiffies&TVR_SIZE 來找到需要運行的定時器任務列表,定時器的插入效率就是O(1)。

下面是定時器的運行代碼:
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);
}
當第一組運行完一輪后,需要將tv2的一組新的定時任務加到第一組。這就好比時鐘的指針,秒針運行一圈后,分針步進一格,后續的調整都是類似。
cascade 就是負責將下一組的定時任務添加到前面的任務階梯。只有當第一輪的定時任務全部運行完畢后,才會需要從第二輪調入新的任務,只有第二級別的任務都調入完畢后,才需要從第三輪的定時任務調入新的任務:
 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));

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

文章轉載請注明出處

常用鏈接

留言簿(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>
            欧美精品在线观看播放| 一本久道久久综合中文字幕| 中文国产亚洲喷潮| 久热精品视频在线| 久久久久**毛片大全| 亚洲一级黄色| 亚洲性视频网站| 亚洲视频中文字幕| 亚洲视频专区在线| 亚洲一区二区视频在线观看| 日韩一级裸体免费视频| 亚洲精品人人| 亚洲欧美一区二区三区久久| 亚洲欧美一区二区三区在线| 欧美在线综合视频| 蜜臀久久99精品久久久久久9| 久久一区二区三区超碰国产精品| 久久国产直播| 欧美黄色视屏| 亚洲一区黄色| 女人香蕉久久**毛片精品| 欧美激情精品久久久| 欧美特黄视频| 亚洲激情视频网| 一本久道久久久| 久久精品女人| 一区二区三区欧美| 99精品99| 亚洲尤物在线| 美女日韩欧美| 在线观看亚洲精品视频| 欧美影院成人| 欧美体内谢she精2性欧美| 亚洲国产片色| 亚洲国内自拍| 国产精品国产三级国产专播精品人 | 亚洲一区二区毛片| 性欧美1819性猛交| 伊甸园精品99久久久久久| 女人天堂亚洲aⅴ在线观看| 欧美一级视频免费在线观看| 亚洲自拍偷拍色片视频| 伊人久久大香线| 国产日韩欧美日韩| 午夜精品三级视频福利| 亚洲精品乱码久久久久久久久| 欧美一区二区三区久久精品 | 国产伦精品一区二区三区视频孕妇 | 亚洲黄网站在线观看| 久久精品夜色噜噜亚洲a∨| 国产亚洲一区二区在线观看| 国产在线不卡视频| 免费成人毛片| 欧美日韩和欧美的一区二区| 中文一区二区| 校园激情久久| 99国产精品视频免费观看一公开| 亚洲电影免费观看高清完整版在线| 久久国产精品久久w女人spa| 国色天香一区二区| 亚洲日本欧美| 国产在线乱码一区二区三区| 欧美高清在线视频| 国产精品萝li| 亚洲国产小视频| 国产亚洲欧美日韩美女| 亚洲美女精品成人在线视频| 国产日韩欧美中文| 日韩视频一区二区在线观看| 国产欧美日韩不卡| 亚洲精品社区| 亚洲日本欧美天堂| 欧美一级成年大片在线观看| 亚洲人成在线观看网站高清| 欧美亚洲免费电影| 欧美一区二区三区电影在线观看| 免费在线欧美黄色| 蜜臀av一级做a爰片久久| 国产日韩成人精品| 亚洲午夜免费视频| 亚洲一区二区影院| 国产精品日韩一区二区| 亚洲日本精品国产第一区| 国产在线拍偷自揄拍精品| 久久国产精品网站| 久久九九国产精品怡红院| 欧美日韩伦理在线免费| 久久综合久色欧美综合狠狠| 国产精品成人一区| 午夜精品网站| 欧美成人自拍| 亚洲香蕉视频| 国内精品**久久毛片app| 久久精品99无色码中文字幕| 美女国产一区| 亚洲一区二区精品在线观看| 国产欧美精品一区二区色综合| 性一交一乱一区二区洋洋av| 久久综合色8888| 亚洲欧美视频在线观看视频| 国产一区二区日韩精品欧美精品| 美女免费视频一区| 亚洲欧美日韩国产综合| 欧美激情国产日韩| 久久精品综合| 亚洲一区二区三区久久 | 一区二区三区|亚洲午夜| 亚洲国产一区二区视频| 蜜桃av一区二区在线观看| 黄色日韩在线| 激情视频一区二区| 好吊日精品视频| 极品av少妇一区二区| 国产精品自拍视频| 欧美日一区二区在线观看| 欧美日韩国产精品| 欧美日韩亚洲激情| 国产精品一区二区在线观看网站| 欧美日韩国产一区二区| 欧美日韩一二三四五区| 欧美亚男人的天堂| 国产精品在线看| 国产在线精品二区| 亚洲精品久久久久久久久久久| 欧美一区二区三区播放老司机| 欧美午夜国产| 国产精品久久久久久久久久久久 | 国产一区二区精品久久91| 午夜精品视频在线观看一区二区| 欧美专区福利在线| 久久综合色8888| 国产精品区一区二区三区| 性欧美8khd高清极品| 欧美色大人视频| 亚洲青色在线| 国产亚洲精品久久飘花| 亚洲美洲欧洲综合国产一区| 国内精品久久久久久久影视蜜臀| 99国产精品久久久| 艳女tv在线观看国产一区| 国产精品久久久免费| 国内精品久久久久久影视8| 女人香蕉久久**毛片精品| 久久一区中文字幕| 欧美日韩国产首页| 国产亚洲欧美日韩在线一区| 国产亚洲毛片| 在线观看成人av| 亚洲永久字幕| 美女在线一区二区| 午夜在线成人av| 久久亚裔精品欧美| 久久综合久色欧美综合狠狠 | 久久亚洲私人国产精品va媚药| 久久久久久久一区二区三区| 麻豆精品国产91久久久久久| 久久激情婷婷| 欧美日韩免费一区二区三区视频| 国产在线播放一区二区三区| 欧美亚洲免费高清在线观看| 亚洲日本无吗高清不卡| 久久久久久久性| 一区二区三区欧美亚洲| 欧美精品在线一区| 亚洲精品在线免费| 一区二区三区 在线观看视频 | 国产一区二区成人久久免费影院| 国产一区二区三区高清播放| 亚洲第一福利在线观看| 欧美专区亚洲专区| 久久人人超碰| 中文在线不卡视频| 亚洲精品日韩综合观看成人91| 久久精品国产v日韩v亚洲| 一区二区三区在线观看国产| 欧美+亚洲+精品+三区| 欧美激情视频网站| 亚洲第一页中文字幕| 猛干欧美女孩| 欧美日本三级| 西西人体一区二区| 香蕉精品999视频一区二区| 国产精品亚洲激情| 亚洲国产欧洲综合997久久| 国产精品电影在线观看| 一本大道久久a久久综合婷婷 | 亚洲日本黄色| 国产在线视频不卡二| 欧美一区二区三区免费看| 亚洲欧美另类中文字幕| 91久久中文| 久久九九有精品国产23| 久久激情婷婷| 亚洲欧美视频在线观看| 国产片一区二区| 一本色道久久综合亚洲精品婷婷| 亚洲成人直播| 欧美三级乱人伦电影| 亚洲国产天堂久久综合| 亚洲国产日韩在线|