-
Inaam Rana authored
Approved by: Marko, Sunny rb://589 This work is performance related. The idea is to off load flushing activity that happens in the LRU list from user threads to the background thread i.e.: the page_cleaner. Also included in the scope is simpler and may be better heuristic for LRU flushing. Summary of Changes: New Config Options: =================== innodb_lru_scan_depth (default 1024): dynamic, min:100, max:~0 innodb_flush_neighbors (default TRUE): dynamic innodb_doublewrite_batch_size (default 120) static, min 1, max 127 (undocumented for internal testing only. enabled when UNIV_PERF_DEBUG is defined) New LRU flushing algorithm: =========================== * LRU flushing happens only in page_cleaner thread * LRU flushing includes cleaning the tail of LRU list AND putting blocks to the free list * When a user threads can't find a block in free list or a clean block in the tail of LRU then it triggers a new type of flush called BUF_FLUSH_SINGLE_PAGE in which it tries to flush a single page from LRU list instead of triggering a batch. Page eviction algorithm: ======================== * iteration 0: * get a block from free list, success:done * if there is an LRU flush batch in progress: * wait for batch to end: retry free list * if buf_pool->try_LRU_scan is set * scan LRU up to srv_LRU_scan_depth to find a clean block * the above will put the block on free list * success:retry the free list * flush one dirty page from tail of LRU to disk * the above will put the block on free list * success: retry the free list * iteration 1: * same as iteration 0 except: * scan whole LRU list * scan LRU list even if buf_pool->try_LRU_scan is not set * iteration > 1: * same as iteration 1 but sleep 100ms Note that potential convoy problem where all user threads try to find a clean page in the tail of the LRU list when there is none is resolved by introducing buf_pool->try_LRU_scan flag which is set to TRUE when an LRU batch is completed and is set to FALSE when an LRU scan fails to find a clean page. Doublewrite buffer changes: =========================== The doublewrite buffer is split into two parts. First part is used for batch flushing (e.g.: LRU flushing and flush_list flushing) while the second part is used for single page flushes. The logic for the batch flushing remains same. For the single page flushing we use a flag to indicate if a slot is in use and we force a write to the disk after writing to the doublewrite buffer right away. There is an undocumented hidden config parameter innodb_doublewrite_batch_size which is visible only with UNIV_PERF_DEBUG or UNIV_DEBUG. The value determines how much of doublewrite is to be used for batch flushing. The default is 120 and allowable values are 1 - 127. It is a static variable. LRU batch size: =============== The size of an LRU batch depends on how deep we scan the LRU list i.e.: innodb_LRU_scan_depth. But since user threads wait for an LRU batch to finish and since the size of doublewrite buffer is 128 it makes sense to divide one big LRU batch into multiple chunks. PAGE_CLEANER_LRU_BATCH_CHUNK_SIZE == 100 does that i.e.: after flushing 100 pages the page cleaner signals waiting user threads to proceed to grab a free page.
Inaam Rana authoredApproved by: Marko, Sunny rb://589 This work is performance related. The idea is to off load flushing activity that happens in the LRU list from user threads to the background thread i.e.: the page_cleaner. Also included in the scope is simpler and may be better heuristic for LRU flushing. Summary of Changes: New Config Options: =================== innodb_lru_scan_depth (default 1024): dynamic, min:100, max:~0 innodb_flush_neighbors (default TRUE): dynamic innodb_doublewrite_batch_size (default 120) static, min 1, max 127 (undocumented for internal testing only. enabled when UNIV_PERF_DEBUG is defined) New LRU flushing algorithm: =========================== * LRU flushing happens only in page_cleaner thread * LRU flushing includes cleaning the tail of LRU list AND putting blocks to the free list * When a user threads can't find a block in free list or a clean block in the tail of LRU then it triggers a new type of flush called BUF_FLUSH_SINGLE_PAGE in which it tries to flush a single page from LRU list instead of triggering a batch. Page eviction algorithm: ======================== * iteration 0: * get a block from free list, success:done * if there is an LRU flush batch in progress: * wait for batch to end: retry free list * if buf_pool->try_LRU_scan is set * scan LRU up to srv_LRU_scan_depth to find a clean block * the above will put the block on free list * success:retry the free list * flush one dirty page from tail of LRU to disk * the above will put the block on free list * success: retry the free list * iteration 1: * same as iteration 0 except: * scan whole LRU list * scan LRU list even if buf_pool->try_LRU_scan is not set * iteration > 1: * same as iteration 1 but sleep 100ms Note that potential convoy problem where all user threads try to find a clean page in the tail of the LRU list when there is none is resolved by introducing buf_pool->try_LRU_scan flag which is set to TRUE when an LRU batch is completed and is set to FALSE when an LRU scan fails to find a clean page. Doublewrite buffer changes: =========================== The doublewrite buffer is split into two parts. First part is used for batch flushing (e.g.: LRU flushing and flush_list flushing) while the second part is used for single page flushes. The logic for the batch flushing remains same. For the single page flushing we use a flag to indicate if a slot is in use and we force a write to the disk after writing to the doublewrite buffer right away. There is an undocumented hidden config parameter innodb_doublewrite_batch_size which is visible only with UNIV_PERF_DEBUG or UNIV_DEBUG. The value determines how much of doublewrite is to be used for batch flushing. The default is 120 and allowable values are 1 - 127. It is a static variable. LRU batch size: =============== The size of an LRU batch depends on how deep we scan the LRU list i.e.: innodb_LRU_scan_depth. But since user threads wait for an LRU batch to finish and since the size of doublewrite buffer is 128 it makes sense to divide one big LRU batch into multiple chunks. PAGE_CLEANER_LRU_BATCH_CHUNK_SIZE == 100 does that i.e.: after flushing 100 pages the page cleaner signals waiting user threads to proceed to grab a free page.
Loading