• bgwriter 的睡眠时间差异


    开始

    简单说就是一开始启动的很频繁(200ms 级),后来没有什么事情可做,就懒惰了。变成了 10秒级别。

    实际验证如下

    postgresql.conf 中和 log 相关部分:

    log_line_prefix = '%m'        
    log_min_messages = info        
    logging_collector = off        

    对 bufmgr.c 的 BgBufferSync的调试:

    bool                
    BgBufferSync(void)                
    {                
                    
        ……            
        /* Execute the LRU scan */            
        while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)            
        {            
                    
                            //added by gaojian        
                            fprintf(stderr,"num_to_scan is: %d \n",num_to_scan);        
                    
            int    buffer_state = SyncOneBuffer(next_to_clean, true);    
                    
            if (++next_to_clean >= NBuffers)        
            {        
                next_to_clean = 0;    
                    
                elog(INFO,"------------------next_passes++.\n");    
                next_passes++;    
            }        
            num_to_scan--;        
                    
            if (buffer_state & BUF_WRITTEN)        
            {        
                reusable_buffers++;    
                if (++num_written >= bgwriter_lru_maxpages)    
                {    
                    BgWriterStats.m_maxwritten_clean++;
                    break;
                }    
            }        
            else if (buffer_state & BUF_REUSABLE)        
                reusable_buffers++;    
        }            
                    
        elog(INFO,".......BgBufferSync Called.");            
        /* Return true if OK to hibernate */            
        return (bufs_to_lap == 0 && recent_alloc == 0);            
    }                
                    

    运行的结果是:

    [作者:技术者高健@博客园  mail: luckyjackgao@gmail.com ]

    [postgres@localhost bin]$ ./postgres -D /usr/local/pgsql/data
    2012-11-02 16:09:55.139 CSTLOG:  database system was shut down at 2012-11-02 16:01:26 CST
    saved_info_valid false.
    2012-11-02 16:09:55.199 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:09:55.199 CSTLOG:  autovacuum launcher started
    2012-11-02 16:09:55.201 CSTLOG:  database system is ready to accept connections
    2012-11-02 16:09:55.399 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:09:55.599 CSTINFO:  .......BgBufferSync Called.
    
    
    ……
    
    2012-11-02 16:12:11.350 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:12:11.550 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:12:11.751 CSTINFO:  ------------------next_passes++.
    
    2012-11-02 16:12:11.751 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:12:11.951 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:12:12.151 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:12:22.360 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:12:32.568 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:12:42.777 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:12:52.985 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:13:03.194 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:13:13.403 CSTINFO:  .......BgBufferSync Called.
    
    2012-11-02 16:13:23.614 CSTINFO:  .......BgBufferSync Called.

    bgwriter 会在循环中 睡眠-->醒来->调用BgBufferSync-->睡眠。

    基本上,其睡眠应该分”浅睡眠“和”深睡眠“

    再回头来看 bgwriter.c 的代码:

    /*                            
     * GUC parameters                            
     */                            
    int            BgWriterDelay = 200;                
                                
    /*                            
     * Multiplier to apply to BgWriterDelay when we decide to hibernate.                            
     * (Perhaps this needs to be configurable?)                            
     */                            
    #define HIBERNATE_FACTOR            50                
                                
    ……                            
                                
    /*                            
     * Main entry point for bgwriter process                            
     *                            
     * This is invoked from AuxiliaryProcessMain, which has already created the                            
     * basic execution environment, but not enabled signals yet.                            
     */                            
    void                            
    BackgroundWriterMain(void)                            
    {                            
        ……                        
        /*                        
         * Loop forever                        
         */                        
        for (;;)                        
        {                        
            ……                    
                                
            /*                    
             * Sleep until we are signaled or BgWriterDelay has elapsed.                    
             *                    
             * Note: the feedback control loop in BgBufferSync() expects that we                    
             * will call it every BgWriterDelay msec.  While it's not critical for                    
             * correctness that that be exact, the feedback loop might misbehave                    
             * if we stray too far from that.  Hence, avoid loading this process                    
             * down with latch events that are likely to happen frequently during                    
             * normal operation.                    
             */                    
            rc = WaitLatch(&MyProc->procLatch,                    
                           WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,        
                           BgWriterDelay /* ms */ );        
                                
            /*                    
             * If no latch event and BgBufferSync says nothing's happening, extend                    
             * the sleep in "hibernation" mode, where we sleep for much longer                    
             * than bgwriter_delay says.  Fewer wakeups save electricity.  When a                    
             * backend starts using buffers again, it will wake us up by setting                    
             * our latch.  Because the extra sleep will persist only as long as no                    
             * buffer allocations happen, this should not distort the behavior of                    
             * BgBufferSync's control loop too badly; essentially, it will think                    
             * that the system-wide idle interval didn't exist.                    
             *                    
             * There is a race condition here, in that a backend might allocate a                    
             * buffer between the time BgBufferSync saw the alloc count as zero                    
             * and the time we call StrategyNotifyBgWriter.  While it's not                    
             * critical that we not hibernate anyway, we try to reduce the odds of                    
             * that by only hibernating when BgBufferSync says nothing's happening                    
             * for two consecutive cycles.    Also, we mitigate any possible                
             * consequences of a missed wakeup by not hibernating forever.                    
             */                    
            if (rc == WL_TIMEOUT && can_hibernate && prev_hibernate)                    
            {                    
                /* Ask for notification at next buffer allocation */                
                StrategyNotifyBgWriter(&MyProc->procLatch);                
                                
                                
                /* Sleep ... */                
                rc = WaitLatch(&MyProc->procLatch,                
                               WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,    
                               BgWriterDelay * HIBERNATE_FACTOR);    
                /* Reset the notification request in case we timed out */                
                StrategyNotifyBgWriter(NULL);                
            }                    
            ……                    
        }                        
    }                            

    可以看到,一开始是睡   BgWriterDelay 就会醒。

    然后,睡了若干次再醒后,如果发现  (rc == WL_TIMEOUT && can_hibernate && prev_hibernate) 得到了满足。

    那么, 就进入新的睡眠模式:

    /* Sleep ... */
    rc = WaitLatch(&MyProc->procLatch,
        WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
          BgWriterDelay * HIBERNATE_FACTOR);

    最后一个参数变成了  BgWriterDelay * HIBERNATE_FACTOR 正好等于 10秒。

    [作者:技术者高健@博客园  mail: luckyjackgao@gmail.com ]

    结束

  • 相关阅读:
    C语言学习趣事_19_C参考手册连接
    2_Windows下利用批处理文件获取命令行命令帮助信息
    C语言学习趣事_FILE_TYPE
    清华大学出版社版_Windows程序设计_方敏_不足_3
    Windows程序设计零基础自学_14_Windows文件和目录操作
    3_Windows下利用批处理文件_去除C源代码中指示行号的前导数字
    随想_7_Windows_7_Visual_Studio_2008_问题
    C语言小算法_1_数值转换
    C语言学习趣事_20_Assert_Setjmp
    C语言学习趣事_20_关于数组名与指针的讨论
  • 原文地址:https://www.cnblogs.com/gaojian/p/2751502.html
Copyright © 2020-2023  润新知