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秒。






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

目录
相关文章
|
机器学习/深度学习 存储 PyTorch
512块A100,AlphaFold训练时间从11天压缩至67小时:尤洋团队FastFold上线
512块A100,AlphaFold训练时间从11天压缩至67小时:尤洋团队FastFold上线
188 0
|
定位技术 C#
C#编程练习(03):北斗时间系统、GPS时间系统及其与UTC时间系统之间的转换
C#编程练习(03):北斗时间系统、GPS时间系统及其与UTC时间系统之间的转换
C#编程练习(03):北斗时间系统、GPS时间系统及其与UTC时间系统之间的转换
把K线的时间增加15分钟
把K线的时间增加15分钟
67 0
|
Unix
strtotime应用(案例:给未来时间添加对应的时间)
strtotime应用(案例:给未来时间添加对应的时间)
192 0
strtotime应用(案例:给未来时间添加对应的时间)
|
机器学习/深度学习 人工智能 数据建模
TPAMI 2021 | 时间走向二维,基于文本的视频时间定位新方法兼顾速度与精度
TPAMI 2021 | 时间走向二维,基于文本的视频时间定位新方法兼顾速度与精度
163 0
TPAMI 2021 | 时间走向二维,基于文本的视频时间定位新方法兼顾速度与精度
|
SQL Oracle 关系型数据库
PostgreSQL 使用逻辑decode实现异步主从切换后,时间线分歧变化量补齐、修复
PostgreSQL 使用逻辑decode实现异步主从切换后,时间线分歧变化量补齐、修复
1312 0
|
C# 网络协议
c#获取网络时间并同步本地时间
原文:c#获取网络时间并同步本地时间 通过TCP形式来获取NTP时间。主要代码如下: [DllImport("kernel32.dll")] private static extern bool SetLocalTime(ref Systemtime time); [StructLayout(LayoutKind.
3036 0
8266获取网络时间
8266获取网络时间 今天第一次用阿里的博客写点东西感受一下....可以参考一下这篇文章,不过有点问题,我后面会说https://www.jianshu.com/p/2d71cc18cfa7 sntp.
2460 0