svn commit: r275488 - in stable/10: cddl/contrib/opensolaris/cmd/zdb sys/cddl/contrib/opensolaris/uts/common/fs/zfs

Xin LI delphij at FreeBSD.org
Thu Dec 4 23:20:45 UTC 2014


Author: delphij
Date: Thu Dec  4 23:20:44 2014
New Revision: 275488
URL: https://svnweb.freebsd.org/changeset/base/275488

Log:
  MFC r274276: MFV r274271:
  
  Improve zdb -b performance:
  
   - Reduce gethrtime() call to 1/100th of blkptr's;
   - Skip manipulating the size-ordered tree;
   - Issue more (10, previously 3) async reads;
   - Use lighter weight testing in traverse_visitbp();
  
  Illumos issue:
      5243 zdb -b could be much faster

Modified:
  stable/10/cddl/contrib/opensolaris/cmd/zdb/zdb.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/cddl/contrib/opensolaris/cmd/zdb/zdb.c
==============================================================================
--- stable/10/cddl/contrib/opensolaris/cmd/zdb/zdb.c	Thu Dec  4 23:19:04 2014	(r275487)
+++ stable/10/cddl/contrib/opensolaris/cmd/zdb/zdb.c	Thu Dec  4 23:20:44 2014	(r275488)
@@ -77,9 +77,11 @@
 #ifndef lint
 extern boolean_t zfs_recover;
 extern uint64_t zfs_arc_max, zfs_arc_meta_limit;
+extern int zfs_vdev_async_read_max_active;
 #else
 boolean_t zfs_recover;
 uint64_t zfs_arc_max, zfs_arc_meta_limit;
+int zfs_vdev_async_read_max_active;
 #endif
 
 const char cmdname[] = "zdb";
@@ -2384,8 +2386,14 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog
 
 	zcb->zcb_readfails = 0;
 
-	if (dump_opt['b'] < 5 &&
-	    gethrtime() > zcb->zcb_lastprint + NANOSEC) {
+	/* only call gethrtime() every 100 blocks */
+	static int iters;
+	if (++iters > 100)
+		iters = 0;
+	else
+		return (0);
+
+	if (dump_opt['b'] < 5 && gethrtime() > zcb->zcb_lastprint + NANOSEC) {
 		uint64_t now = gethrtime();
 		char buf[10];
 		uint64_t bytes = zcb->zcb_type[ZB_TOTAL][ZDB_OT_TOTAL].zb_asize;
@@ -2494,6 +2502,14 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
 					    (longlong_t)vd->vdev_ms_count);
 
 					msp->ms_ops = &zdb_metaslab_ops;
+
+					/*
+					 * We don't want to spend the CPU
+					 * manipulating the size-ordered
+					 * tree, so clear the range_tree
+					 * ops.
+					 */
+					msp->ms_tree->rt_ops = NULL;
 					VERIFY0(space_map_load(msp->ms_sm,
 					    msp->ms_tree, SM_ALLOC));
 					msp->ms_loaded = B_TRUE;
@@ -3508,6 +3524,13 @@ main(int argc, char **argv)
 	 */
 	zfs_arc_max = zfs_arc_meta_limit = 256 * 1024 * 1024;
 
+	/*
+	 * "zdb -c" uses checksum-verifying scrub i/os which are async reads.
+	 * "zdb -b" uses traversal prefetch which uses async reads.
+	 * For good performance, let several of them be active at once.
+	 */
+	zfs_vdev_async_read_max_active = 10;
+
 	kernel_init(FREAD);
 	g_zfs = libzfs_init();
 	ASSERT(g_zfs != NULL);

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c	Thu Dec  4 23:19:04 2014	(r275487)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c	Thu Dec  4 23:20:44 2014	(r275488)
@@ -59,6 +59,7 @@ typedef struct traverse_data {
 	int td_flags;
 	prefetch_data_t *td_pfd;
 	boolean_t td_paused;
+	uint64_t td_hole_birth_enabled_txg;
 	blkptr_cb_t *td_func;
 	void *td_arg;
 } traverse_data_t;
@@ -229,25 +230,20 @@ traverse_visitbp(traverse_data_t *td, co
 	}
 
 	if (bp->blk_birth == 0) {
-		if (spa_feature_is_active(td->td_spa, SPA_FEATURE_HOLE_BIRTH)) {
-			/*
-			 * Since this block has a birth time of 0 it must be a
-			 * hole created before the SPA_FEATURE_HOLE_BIRTH
-			 * feature was enabled.  If SPA_FEATURE_HOLE_BIRTH
-			 * was enabled before the min_txg for this traveral we
-			 * know the hole must have been created before the
-			 * min_txg for this traveral, so we can skip it. If
-			 * SPA_FEATURE_HOLE_BIRTH was enabled after the min_txg
-			 * for this traveral we cannot tell if the hole was
-			 * created before or after the min_txg for this
-			 * traversal, so we cannot skip it.
-			 */
-			uint64_t hole_birth_enabled_txg;
-			VERIFY(spa_feature_enabled_txg(td->td_spa,
-			    SPA_FEATURE_HOLE_BIRTH, &hole_birth_enabled_txg));
-			if (hole_birth_enabled_txg < td->td_min_txg)
-				return (0);
-		}
+		/*
+		 * Since this block has a birth time of 0 it must be a
+		 * hole created before the SPA_FEATURE_HOLE_BIRTH
+		 * feature was enabled.  If SPA_FEATURE_HOLE_BIRTH
+		 * was enabled before the min_txg for this traveral we
+		 * know the hole must have been created before the
+		 * min_txg for this traveral, so we can skip it. If
+		 * SPA_FEATURE_HOLE_BIRTH was enabled after the min_txg
+		 * for this traveral we cannot tell if the hole was
+		 * created before or after the min_txg for this
+		 * traversal, so we cannot skip it.
+		 */
+		if (td->td_hole_birth_enabled_txg < td->td_min_txg)
+			return (0);
 	} else if (bp->blk_birth <= td->td_min_txg) {
 		return (0);
 	}
@@ -523,6 +519,13 @@ traverse_impl(spa_t *spa, dsl_dataset_t 
 	td.td_flags = flags;
 	td.td_paused = B_FALSE;
 
+	if (spa_feature_is_active(spa, SPA_FEATURE_HOLE_BIRTH)) {
+		VERIFY(spa_feature_enabled_txg(spa,
+		    SPA_FEATURE_HOLE_BIRTH, &td.td_hole_birth_enabled_txg));
+	} else {
+		td.td_hole_birth_enabled_txg = 0;
+	}
+
 	pd.pd_blks_max = zfs_pd_blks_max;
 	pd.pd_flags = flags;
 	mutex_init(&pd.pd_mtx, NULL, MUTEX_DEFAULT, NULL);


More information about the svn-src-all mailing list