bgwriter 的睡眠时间差异

开始

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

实际验证如下

postgresql.conf 中和 log 相关部分:

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

对 bufmgr.c 的 BgBufferSync的调试:

bgwriter 的睡眠时间差异
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);            
}                
                
bgwriter 的睡眠时间差异

运行的结果是:

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

bgwriter 的睡眠时间差异
[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 的睡眠时间差异

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

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

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

bgwriter 的睡眠时间差异
/*                            
 * 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);                
        }                    
        ……                    
    }                        
}                            
bgwriter 的睡眠时间差异

可以看到,一开始是睡   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秒。






本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/11/02/2751502.html,如需转载请自行联系原作者

上一篇:人人都是Serverless架构师之Serverless架构简介


下一篇:关于函数计算异步调用异常的处理方法