diff options
author | Alex Gorrod <alexg@wiredtiger.com> | 2012-11-28 10:30:37 +1100 |
---|---|---|
committer | Alex Gorrod <alexg@wiredtiger.com> | 2012-11-28 10:30:37 +1100 |
commit | 45a13edceabecaa1544e99db7b6c51f60d6a34c7 (patch) | |
tree | c4158ea87f12345e496fb45e48ae5207c483a2a2 | |
parent | 91d9d8ef94513923a446f9fdab596aa2951ff1f2 (diff) | |
download | mongo-45a13edceabecaa1544e99db7b6c51f60d6a34c7.tar.gz |
Fix tracking of dirty pages. Add statistics for dirty pages.
-rw-r--r-- | dist/stat_data.py | 4 | ||||
-rw-r--r-- | examples/c/ex_all.c | 2 | ||||
-rw-r--r-- | src/btree/bt_handle.c | 2 | ||||
-rw-r--r-- | src/btree/bt_page.c | 2 | ||||
-rw-r--r-- | src/btree/bt_read.c | 2 | ||||
-rw-r--r-- | src/btree/bt_slvg.c | 2 | ||||
-rw-r--r-- | src/btree/bt_sync.c | 2 | ||||
-rw-r--r-- | src/btree/bt_walk.c | 2 | ||||
-rw-r--r-- | src/btree/rec_write.c | 11 | ||||
-rw-r--r-- | src/conn/conn_cache.c | 52 | ||||
-rw-r--r-- | src/conn/conn_stat.c | 2 | ||||
-rw-r--r-- | src/include/btree.i | 36 | ||||
-rw-r--r-- | src/include/extern.h | 2 | ||||
-rw-r--r-- | src/include/stat.h | 4 | ||||
-rw-r--r-- | src/include/wiredtiger.in | 52 | ||||
-rw-r--r-- | src/support/stat.c | 12 |
16 files changed, 135 insertions, 54 deletions
diff --git a/dist/stat_data.py b/dist/stat_data.py index 2129b72dfa9..21f25b2db32 100644 --- a/dist/stat_data.py +++ b/dist/stat_data.py @@ -22,6 +22,8 @@ class Stat: connection_stats = [ Stat('block_read', 'blocks read from a file'), Stat('block_write', 'blocks written to a file'), + Stat('cache_bytes_dirty', 'cache: tracked dirty bytes in the cache'), + Stat('cache_bytes_dirty_calc', 'cache: counted dirty bytes in the cache'), Stat('cache_bytes_inuse', 'cache: bytes currently held in the cache', perm=1), Stat('cache_bytes_max', 'cache: maximum bytes configured', perm=1), @@ -32,6 +34,8 @@ connection_stats = [ Stat('cache_evict_slow', 'cache: eviction server unable to reach eviction goal'), Stat('cache_evict_unmodified', 'cache: unmodified pages evicted'), + Stat('cache_pages_dirty', 'cache: tracked dirty pages in the cache'), + Stat('cache_pages_dirty_calc', 'cache: counted dirty pages in the cache'), Stat('cache_pages_inuse', 'cache: pages currently held in the cache', perm=1), Stat('checkpoint', 'checkpoints'), diff --git a/examples/c/ex_all.c b/examples/c/ex_all.c index 710065f32b5..a4512b33f28 100644 --- a/examples/c/ex_all.c +++ b/examples/c/ex_all.c @@ -806,7 +806,7 @@ connection_ops(WT_CONNECTION *conn) /*! [Setup cache dirty target] */ ret = conn->reconfigure(conn, "eviction_dirty_target=75"); - /*! [Reconfigure a connection] */ + /*! [Setup cache dirty target] */ /*! [Get the database home directory] */ printf("The database home is %s\n", conn->get_home(conn)); diff --git a/src/btree/bt_handle.c b/src/btree/bt_handle.c index 64e692d1cbb..99e91566e46 100644 --- a/src/btree/bt_handle.c +++ b/src/btree/bt_handle.c @@ -380,7 +380,7 @@ __btree_tree_open_empty(WT_SESSION_IMPL *session, int created) * or it's actually modified. */ WT_ERR(__wt_page_modify_init(session, leaf)); - __wt_page_modify_set(leaf); + __wt_page_modify_set(session, leaf); btree->root_page = root; diff --git a/src/btree/bt_page.c b/src/btree/bt_page.c index cd74e3cdc87..7ea6318226f 100644 --- a/src/btree/bt_page.c +++ b/src/btree/bt_page.c @@ -389,7 +389,7 @@ __inmem_row_int(WT_SESSION_IMPL *session, WT_PAGE *page, size_t *inmem_sizep) WT_ERR(__wt_page_modify_init(session, page)); page->modify->first_id = WT_TXN_NONE; if (btree->modified) - __wt_page_modify_set(page); + __wt_page_modify_set(session, page); } ++ref; diff --git a/src/btree/bt_read.c b/src/btree/bt_read.c index e86f4ccd8d7..0830963eb2c 100644 --- a/src/btree/bt_read.c +++ b/src/btree/bt_read.c @@ -33,7 +33,7 @@ __cache_read_row_deleted( WT_RET(__wt_page_modify_init(session, page)); page->modify->first_id = ref->txnid; if (btree->modified) - __wt_page_modify_set(page); + __wt_page_modify_set(session, page); /* Allocate the update array. */ WT_RET(__wt_calloc_def(session, page->entries, &upd_array)); diff --git a/src/btree/bt_slvg.c b/src/btree/bt_slvg.c index 4a1e5c4a77e..c332fd8e39e 100644 --- a/src/btree/bt_slvg.c +++ b/src/btree/bt_slvg.c @@ -1049,7 +1049,7 @@ __slvg_modify_init(WT_SESSION_IMPL *session, WT_PAGE *page) /* The page is dirty. */ WT_RET(__wt_page_modify_init(session, page)); - __wt_page_modify_set(page); + __wt_page_modify_set(session, page); return (0); } diff --git a/src/btree/bt_sync.c b/src/btree/bt_sync.c index bb05f966ee4..bf6505da3a7 100644 --- a/src/btree/bt_sync.c +++ b/src/btree/bt_sync.c @@ -22,7 +22,7 @@ __wt_bt_cache_force_write(WT_SESSION_IMPL *session) /* Dirty the root page to ensure a write. */ WT_RET(__wt_page_modify_init(session, page)); - __wt_page_modify_set(page); + __wt_page_modify_set(session, page); return (0); } diff --git a/src/btree/bt_walk.c b/src/btree/bt_walk.c index 7fcedbdd1e2..8c0e033ef80 100644 --- a/src/btree/bt_walk.c +++ b/src/btree/bt_walk.c @@ -95,7 +95,7 @@ __tree_walk_delete( * we write the tree. */ WT_ERR(__wt_page_modify_init(session, page)); - __wt_page_modify_set(page); + __wt_page_modify_set(session, page); *skipp = 1; diff --git a/src/btree/rec_write.c b/src/btree/rec_write.c index 360e184da75..fa789072fda 100644 --- a/src/btree/rec_write.c +++ b/src/btree/rec_write.c @@ -476,7 +476,7 @@ __wt_rec_write(WT_SESSION_IMPL *session, break; } WT_RET(__wt_page_modify_init(session, page)); - __wt_page_modify_set(page); + __wt_page_modify_set(session, page); return (0); } @@ -524,7 +524,7 @@ __wt_rec_write(WT_SESSION_IMPL *session, WT_VERBOSE_RET(session, reconcile, "root page split %p -> %p", page, page->modify->u.split); page = page->modify->u.split; - __wt_page_modify_set(page); + __wt_page_modify_set(session, page); F_CLR(page->modify, WT_PM_REC_SPLIT_MERGE); WT_RET(__wt_rec_write(session, page, NULL, flags)); @@ -1389,7 +1389,7 @@ __wt_rec_bulk_wrapup(WT_CURSOR_BULK *cbulk) /* Mark the page's parent dirty. */ WT_RET(__wt_page_modify_init(session, page->parent)); - __wt_page_modify_set(page->parent); + __wt_page_modify_set(session, page->parent); __wt_rec_destroy(session, &cbulk->reconcile); @@ -3178,6 +3178,7 @@ __rec_write_wrapup(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) WT_DECL_RET; WT_PAGE_MODIFY *mod; uint32_t i; + int was_modified; btree = session->btree; mod = page->modify; @@ -3375,8 +3376,10 @@ err: __wt_scr_free(&tkey); * started. */ if (!r->upd_skipped) { - __wt_cache_dirty_decr(session, page->memory_footprint); + was_modified = __wt_page_is_modified(page); mod->disk_gen = r->orig_write_gen; + if (was_modified && !__wt_page_is_modified(page)) + __wt_cache_dirty_decr(session, page->memory_footprint); } return (0); diff --git a/src/conn/conn_cache.c b/src/conn/conn_cache.c index 1f8afc3fe97..ed056bb4fe5 100644 --- a/src/conn/conn_cache.c +++ b/src/conn/conn_cache.c @@ -7,6 +7,8 @@ #include "wt_internal.h" +static void __cache_stats_traverse(WT_CONNECTION_IMPL *conn); + /* * __wt_cache_config -- * Configure the underlying cache. @@ -88,7 +90,7 @@ __wt_cache_create(WT_CONNECTION_IMPL *conn, const char *cfg[]) * We pull some values from the cache statistics (rather than have two * copies). Set them. */ - __wt_cache_stats_update(conn); + __wt_cache_stats_update(conn, 0); return (0); @@ -101,7 +103,7 @@ err: __wt_cache_destroy(conn); * Update the cache statistics for return to the application. */ void -__wt_cache_stats_update(WT_CONNECTION_IMPL *conn) +__wt_cache_stats_update(WT_CONNECTION_IMPL *conn, uint32_t flags) { WT_CACHE *cache; @@ -112,6 +114,52 @@ __wt_cache_stats_update(WT_CONNECTION_IMPL *conn) conn->stats, cache_bytes_inuse, __wt_cache_bytes_inuse(cache)); WT_STAT_SET( conn->stats, cache_pages_inuse, __wt_cache_pages_inuse(cache)); + WT_STAT_SET( + conn->stats, cache_bytes_dirty, __wt_cache_dirty_bytes(cache)); + WT_STAT_SET( + conn->stats, cache_pages_dirty, cache->pages_dirty); + + if (!LF_ISSET(WT_STATISTICS_FAST)) + __cache_stats_traverse(conn); +} + +/* + * __cache_stats_traverse -- + * Generate statistics that require traversing the cache. + */ +static void +__cache_stats_traverse(WT_CONNECTION_IMPL *conn) +{ + WT_BTREE *btree; + WT_CACHE *cache; + WT_DECL_RET; + WT_PAGE *page; + WT_SESSION_IMPL *session; + + cache = conn->cache; + session = conn->default_session; + page = NULL; + btree = NULL; + + WT_STAT_SET(conn->stats, cache_bytes_dirty_calc, 0); + WT_STAT_SET(conn->stats, cache_pages_dirty_calc, 0); + + TAILQ_FOREACH(btree, &conn->btqh, q) { + /* Reference the correct WT_BTREE handle. */ + WT_SET_BTREE_IN_SESSION(session, btree); + while ((ret = __wt_tree_walk( + session, &page, WT_TREE_EVICT)) == 0 && + page != NULL) { + if (__wt_page_is_modified(page)) { + WT_STAT_INCRV(conn->stats, + cache_bytes_dirty_calc, + page->memory_footprint); + WT_STAT_INCRV(conn->stats, + cache_pages_dirty_calc, 1); + } + } + WT_CLEAR_BTREE_IN_SESSION(session); + } } /* diff --git a/src/conn/conn_stat.c b/src/conn/conn_stat.c index df861665b4b..154689f80de 100644 --- a/src/conn/conn_stat.c +++ b/src/conn/conn_stat.c @@ -19,5 +19,5 @@ __wt_conn_stat_init(WT_SESSION_IMPL *session, uint32_t flags) WT_UNUSED(flags); conn = S2C(session); - __wt_cache_stats_update(conn); + __wt_cache_stats_update(conn, flags); } diff --git a/src/include/btree.i b/src/include/btree.i index c98c3a33355..edc04e4959f 100644 --- a/src/include/btree.i +++ b/src/include/btree.i @@ -38,10 +38,13 @@ static inline void __wt_cache_page_inmem_decr( WT_SESSION_IMPL *session, WT_PAGE *page, size_t size) { - (void)WT_ATOMIC_SUB(S2C(session)->cache->bytes_inmem, size); + WT_CACHE *cache; + cache = S2C(session)->cache; + + (void)WT_ATOMIC_SUB(cache->bytes_inmem, size); (void)WT_ATOMIC_SUB(page->memory_footprint, WT_STORE_SIZE(size)); if (__wt_page_is_modified(page)) - (void)WT_ATOMIC_SUB(S2C(session)->cache->bytes_dirty, size); + (void)WT_ATOMIC_SUB(cache->bytes_dirty, size); } /* @@ -53,8 +56,13 @@ static inline void __wt_cache_dirty_decr( WT_SESSION_IMPL *session, size_t size) { - (void)WT_ATOMIC_SUB( - S2C(session)->cache->bytes_dirty, size); + WT_CACHE *cache; + cache = S2C(session)->cache; + + WT_ASSERT(session, + cache->bytes_dirty >= size && cache->pages_dirty > 0); + (void)WT_ATOMIC_SUB(cache->bytes_dirty, size); + (void)WT_ATOMIC_SUB(cache->pages_dirty, 1); } /* @@ -91,12 +99,6 @@ __wt_cache_page_evict(WT_SESSION_IMPL *session, WT_PAGE *page) (void)WT_ATOMIC_ADD(cache->pages_evict, 1); (void)WT_ATOMIC_ADD(cache->bytes_evict, page->memory_footprint); - if (__wt_page_is_modified(page)) { - (void)WT_ATOMIC_SUB(cache->pages_dirty, 1); - WT_ASSERT(session, cache->bytes_dirty > page->memory_footprint); - (void)WT_ATOMIC_SUB(cache->bytes_dirty, page->memory_footprint); - } - page->memory_footprint = 0; } @@ -176,11 +178,6 @@ __wt_page_modify_init(WT_SESSION_IMPL *session, WT_PAGE *page) */ if (!WT_ATOMIC_CAS(page->modify, NULL, modify)) __wt_free(session, modify); - else { - (void)WT_ATOMIC_ADD(S2C(session)->cache->pages_dirty, 1); - (void)WT_ATOMIC_ADD( - S2C(session)->cache->bytes_dirty, page->memory_footprint); - } return (0); } @@ -189,8 +186,13 @@ __wt_page_modify_init(WT_SESSION_IMPL *session, WT_PAGE *page) * Mark the page dirty. */ static inline void -__wt_page_modify_set(WT_PAGE *page) +__wt_page_modify_set(WT_SESSION_IMPL *session, WT_PAGE *page) { + if (!__wt_page_is_modified(page)) { + (void)WT_ATOMIC_ADD(S2C(session)->cache->pages_dirty, 1); + (void)WT_ATOMIC_ADD( + S2C(session)->cache->bytes_dirty, page->memory_footprint); + } /* * Publish: there must be a barrier to ensure all changes to the page * are flushed before we update the page's write generation, otherwise @@ -220,7 +222,7 @@ __wt_page_and_tree_modify_set(WT_SESSION_IMPL *session, WT_PAGE *page) */ btree->modified = 1; - __wt_page_modify_set(page); + __wt_page_modify_set(session, page); } /* diff --git a/src/include/extern.h b/src/include/extern.h index 09826b23a4d..16f5328b421 100644 --- a/src/include/extern.h +++ b/src/include/extern.h @@ -605,7 +605,7 @@ extern const char *__wt_confdfl_wiredtiger_open; extern WT_CONFIG_CHECK __wt_confchk_wiredtiger_open[]; extern int __wt_cache_config(WT_CONNECTION_IMPL *conn, const char *cfg[]); extern int __wt_cache_create(WT_CONNECTION_IMPL *conn, const char *cfg[]); -extern void __wt_cache_stats_update(WT_CONNECTION_IMPL *conn); +extern void __wt_cache_stats_update(WT_CONNECTION_IMPL *conn, uint32_t flags); extern void __wt_cache_destroy(WT_CONNECTION_IMPL *conn); extern int __wt_conn_cache_pool_config(WT_SESSION_IMPL *session, const char **cfg); diff --git a/src/include/stat.h b/src/include/stat.h index 9f8445cc5e8..9fa5e8b3e10 100644 --- a/src/include/stat.h +++ b/src/include/stat.h @@ -138,6 +138,8 @@ struct __wt_dsrc_stats { struct __wt_connection_stats { WT_STATS block_read; WT_STATS block_write; + WT_STATS cache_bytes_dirty; + WT_STATS cache_bytes_dirty_calc; WT_STATS cache_bytes_inuse; WT_STATS cache_bytes_max; WT_STATS cache_evict_hazard; @@ -145,6 +147,8 @@ struct __wt_connection_stats { WT_STATS cache_evict_modified; WT_STATS cache_evict_slow; WT_STATS cache_evict_unmodified; + WT_STATS cache_pages_dirty; + WT_STATS cache_pages_dirty_calc; WT_STATS cache_pages_inuse; WT_STATS checkpoint; WT_STATS cond_wait; diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in index dfbab5be762..5d5bdcb1fab 100644 --- a/src/include/wiredtiger.in +++ b/src/include/wiredtiger.in @@ -1706,51 +1706,59 @@ extern int wiredtiger_extension_init(WT_SESSION *session, #define WT_STAT_CONN_BLOCK_READ 0 /*! blocks written to a file */ #define WT_STAT_CONN_BLOCK_WRITE 1 +/*! cache: tracked dirty bytes in the cache */ +#define WT_STAT_CONN_CACHE_BYTES_DIRTY 2 +/*! cache: counted dirty bytes in the cache */ +#define WT_STAT_CONN_CACHE_BYTES_DIRTY_CALC 3 /*! cache: bytes currently held in the cache */ -#define WT_STAT_CONN_CACHE_BYTES_INUSE 2 +#define WT_STAT_CONN_CACHE_BYTES_INUSE 4 /*! cache: maximum bytes configured */ -#define WT_STAT_CONN_CACHE_BYTES_MAX 3 +#define WT_STAT_CONN_CACHE_BYTES_MAX 5 /*! cache: pages selected for eviction not evicted because of a hazard * reference */ -#define WT_STAT_CONN_CACHE_EVICT_HAZARD 4 +#define WT_STAT_CONN_CACHE_EVICT_HAZARD 6 /*! cache: internal pages evicted */ -#define WT_STAT_CONN_CACHE_EVICT_INTERNAL 5 +#define WT_STAT_CONN_CACHE_EVICT_INTERNAL 7 /*! cache: modified pages evicted */ -#define WT_STAT_CONN_CACHE_EVICT_MODIFIED 6 +#define WT_STAT_CONN_CACHE_EVICT_MODIFIED 8 /*! cache: eviction server unable to reach eviction goal */ -#define WT_STAT_CONN_CACHE_EVICT_SLOW 7 +#define WT_STAT_CONN_CACHE_EVICT_SLOW 9 /*! cache: unmodified pages evicted */ -#define WT_STAT_CONN_CACHE_EVICT_UNMODIFIED 8 +#define WT_STAT_CONN_CACHE_EVICT_UNMODIFIED 10 +/*! cache: tracked dirty pages in the cache */ +#define WT_STAT_CONN_CACHE_PAGES_DIRTY 11 +/*! cache: counted dirty pages in the cache */ +#define WT_STAT_CONN_CACHE_PAGES_DIRTY_CALC 12 /*! cache: pages currently held in the cache */ -#define WT_STAT_CONN_CACHE_PAGES_INUSE 9 +#define WT_STAT_CONN_CACHE_PAGES_INUSE 13 /*! checkpoints */ -#define WT_STAT_CONN_CHECKPOINT 10 +#define WT_STAT_CONN_CHECKPOINT 14 /*! condition wait calls */ -#define WT_STAT_CONN_COND_WAIT 11 +#define WT_STAT_CONN_COND_WAIT 15 /*! files currently open */ -#define WT_STAT_CONN_FILE_OPEN 12 +#define WT_STAT_CONN_FILE_OPEN 16 /*! total memory allocations */ -#define WT_STAT_CONN_MEMALLOC 13 +#define WT_STAT_CONN_MEMALLOC 17 /*! total memory frees */ -#define WT_STAT_CONN_MEMFREE 14 +#define WT_STAT_CONN_MEMFREE 18 /*! rwlock readlock calls */ -#define WT_STAT_CONN_RWLOCK_RDLOCK 15 +#define WT_STAT_CONN_RWLOCK_RDLOCK 19 /*! rwlock writelock calls */ -#define WT_STAT_CONN_RWLOCK_WRLOCK 16 +#define WT_STAT_CONN_RWLOCK_WRLOCK 20 /*! total read I/Os */ -#define WT_STAT_CONN_TOTAL_READ_IO 17 +#define WT_STAT_CONN_TOTAL_READ_IO 21 /*! total write I/Os */ -#define WT_STAT_CONN_TOTAL_WRITE_IO 18 +#define WT_STAT_CONN_TOTAL_WRITE_IO 22 /*! ancient transactions */ -#define WT_STAT_CONN_TXN_ANCIENT 19 +#define WT_STAT_CONN_TXN_ANCIENT 23 /*! transactions */ -#define WT_STAT_CONN_TXN_BEGIN 20 +#define WT_STAT_CONN_TXN_BEGIN 24 /*! transactions committed */ -#define WT_STAT_CONN_TXN_COMMIT 21 +#define WT_STAT_CONN_TXN_COMMIT 25 /*! transaction failures due to cache overflow */ -#define WT_STAT_CONN_TXN_FAIL_CACHE 22 +#define WT_STAT_CONN_TXN_FAIL_CACHE 26 /*! transactions rolled-back */ -#define WT_STAT_CONN_TXN_ROLLBACK 23 +#define WT_STAT_CONN_TXN_ROLLBACK 27 /*! * @} diff --git a/src/support/stat.c b/src/support/stat.c index b79f7f3e8e5..11d717824f5 100644 --- a/src/support/stat.c +++ b/src/support/stat.c @@ -155,6 +155,10 @@ __wt_stat_alloc_connection_stats(WT_SESSION_IMPL *session, WT_CONNECTION_STATS * stats->block_read.desc = "blocks read from a file"; stats->block_write.desc = "blocks written to a file"; + stats->cache_bytes_dirty.desc = + "cache: tracked dirty bytes in the cache"; + stats->cache_bytes_dirty_calc.desc = + "cache: counted dirty bytes in the cache"; stats->cache_bytes_inuse.desc = "cache: bytes currently held in the cache"; stats->cache_bytes_max.desc = "cache: maximum bytes configured"; @@ -165,6 +169,10 @@ __wt_stat_alloc_connection_stats(WT_SESSION_IMPL *session, WT_CONNECTION_STATS * stats->cache_evict_slow.desc = "cache: eviction server unable to reach eviction goal"; stats->cache_evict_unmodified.desc = "cache: unmodified pages evicted"; + stats->cache_pages_dirty.desc = + "cache: tracked dirty pages in the cache"; + stats->cache_pages_dirty_calc.desc = + "cache: counted dirty pages in the cache"; stats->cache_pages_inuse.desc = "cache: pages currently held in the cache"; stats->checkpoint.desc = "checkpoints"; @@ -195,11 +203,15 @@ __wt_stat_clear_connection_stats(WT_STATS *stats_arg) stats = (WT_CONNECTION_STATS *)stats_arg; stats->block_read.v = 0; stats->block_write.v = 0; + stats->cache_bytes_dirty.v = 0; + stats->cache_bytes_dirty_calc.v = 0; stats->cache_evict_hazard.v = 0; stats->cache_evict_internal.v = 0; stats->cache_evict_modified.v = 0; stats->cache_evict_slow.v = 0; stats->cache_evict_unmodified.v = 0; + stats->cache_pages_dirty.v = 0; + stats->cache_pages_dirty_calc.v = 0; stats->checkpoint.v = 0; stats->cond_wait.v = 0; stats->file_open.v = 0; |