Re: [PATCH] [RFC] xfs: make xfs btree stats less huge

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Sep 13, 2016 at 06:28:42PM +1000, Dave Chinner wrote:
> From: Dave Chinner <dchinner@xxxxxxxxxx>
> 
> Embedding a switch statement in every btree stats inc/add adds a lot
> of code overhead to the core btree infrastructure paths. Stats are
> supposed to be small and lightweight, but the btree stats have
> become big and bloated as we've added more btrees. It needs fixing
> because the reflink code will just add more overhead again.
> 
> Convert the v2 btree stats to arrays instead of independent
> variables, and instead use the type to index the specific btree
> array via an enum. This allows us to use array based indexing
> to update the stats, rather than having to derefence variables
> specific to the btree type.
> 
> If we then wrap the xfsstats structure in a union and place uint32_t
> array beside it, and calculate the correct btree stats array base
> array index when creating a btree cursor,  we can easily access
> entries in the stats structure without having to switch names based
> on the btree type.
> 
> We then replace with the switch statement with a simple set of stats
> wrapper macros, resulting in a significant simplification of the
> btree stats code, and:
> 
>    text	   data	    bss	    dec	    hex	filename
>   46485	    144	      8	  46637	   b62d fs/xfs/libxfs/xfs_btree.o.old
>   35957	    144	      8	  36109	   8d0d	fs/xfs/libxfs/xfs_btree.o
> 
> it reduces the core btree infrastructure code size by close to 25%!
> 
> Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
> ---
>  fs/xfs/libxfs/xfs_alloc_btree.c  |   4 +
>  fs/xfs/libxfs/xfs_bmap_btree.c   |   1 +
>  fs/xfs/libxfs/xfs_btree.h        |  40 +--------
>  fs/xfs/libxfs/xfs_ialloc_btree.c |   2 +
>  fs/xfs/libxfs/xfs_rmap_btree.c   |   1 +
>  fs/xfs/xfs_stats.c               |  10 +--
>  fs/xfs/xfs_stats.h               | 174 ++++++++++++++++-----------------------
>  7 files changed, 88 insertions(+), 144 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c
> index 5ba2dac..44cfcd0 100644
> --- a/fs/xfs/libxfs/xfs_alloc_btree.c
> +++ b/fs/xfs/libxfs/xfs_alloc_btree.c
> @@ -428,6 +428,10 @@ xfs_allocbt_init_cursor(
>  	cur->bc_btnum = btnum;
>  	cur->bc_blocklog = mp->m_sb.sb_blocklog;
>  	cur->bc_ops = &xfs_allocbt_ops;
> +	if (btnum == XFS_BTNUM_BNO)
> +		cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtb_2);
> +	else
> +		cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtc_2);
>  
>  	if (btnum == XFS_BTNUM_CNT) {
>  		cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
> diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
> index cd85274..5c32e65 100644
> --- a/fs/xfs/libxfs/xfs_bmap_btree.c
> +++ b/fs/xfs/libxfs/xfs_bmap_btree.c
> @@ -785,6 +785,7 @@ xfs_bmbt_init_cursor(
>  	cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
>  	cur->bc_btnum = XFS_BTNUM_BMAP;
>  	cur->bc_blocklog = mp->m_sb.sb_blocklog;
> +	cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2);
>  
>  	cur->bc_ops = &xfs_bmbt_ops;
>  	cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE;
> diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
> index 04d0865..c464cb3 100644
> --- a/fs/xfs/libxfs/xfs_btree.h
> +++ b/fs/xfs/libxfs/xfs_btree.h
> @@ -105,43 +105,10 @@ union xfs_btree_rec {
>  /*
>   * Generic stats interface
>   */
> -#define __XFS_BTREE_STATS_INC(mp, type, stat) \
> -	XFS_STATS_INC(mp, xs_ ## type ## _2_ ## stat)
>  #define XFS_BTREE_STATS_INC(cur, stat)	\
> -do {    \
> -	struct xfs_mount *__mp = cur->bc_mp; \
> -	switch (cur->bc_btnum) {  \
> -	case XFS_BTNUM_BNO: __XFS_BTREE_STATS_INC(__mp, abtb, stat); break; \
> -	case XFS_BTNUM_CNT: __XFS_BTREE_STATS_INC(__mp, abtc, stat); break; \
> -	case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \
> -	case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \
> -	case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \
> -	case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \
> -	case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break;	\

Yay, this stupid thing goes away!!!

> -	}       \
> -} while (0)
> -
> -#define __XFS_BTREE_STATS_ADD(mp, type, stat, val) \
> -	XFS_STATS_ADD(mp, xs_ ## type ## _2_ ## stat, val)
> -#define XFS_BTREE_STATS_ADD(cur, stat, val)  \
> -do {    \
> -	struct xfs_mount *__mp = cur->bc_mp; \
> -	switch (cur->bc_btnum) {  \
> -	case XFS_BTNUM_BNO:	\
> -		__XFS_BTREE_STATS_ADD(__mp, abtb, stat, val); break; \
> -	case XFS_BTNUM_CNT:	\
> -		__XFS_BTREE_STATS_ADD(__mp, abtc, stat, val); break; \
> -	case XFS_BTNUM_BMAP:	\
> -		__XFS_BTREE_STATS_ADD(__mp, bmbt, stat, val); break; \
> -	case XFS_BTNUM_INO:	\
> -		__XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \
> -	case XFS_BTNUM_FINO:	\
> -		__XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \
> -	case XFS_BTNUM_RMAP:	\
> -		__XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \
> -	case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \
> -	}       \
> -} while (0)
> +	XFS_STATS_INC_OFF((cur)->bc_mp, (cur)->bc_statoff + __XBTS_ ## stat)
> +#define XFS_BTREE_STATS_ADD(cur, stat, val)	\
> +	XFS_STATS_ADD_OFF((cur)->bc_mp, (cur)->bc_statoff + __XBTS_ ## stat, val)
>  
>  #define	XFS_BTREE_MAXLEVELS	9	/* max of all btrees */
>  
> @@ -250,6 +217,7 @@ typedef struct xfs_btree_cur
>  	__uint8_t	bc_nlevels;	/* number of levels in the tree */
>  	__uint8_t	bc_blocklog;	/* log2(blocksize) of btree blocks */
>  	xfs_btnum_t	bc_btnum;	/* identifies which btree type */
> +	int		bc_statoff;	/* offset of btre stats array */

/* offset of the btree stats array */

>  	union {
>  		struct {			/* needed for BNO, CNT, INO */
>  			struct xfs_buf	*agbp;	/* agf/agi buffer pointer */
> diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
> index 31ca220..f93c288 100644
> --- a/fs/xfs/libxfs/xfs_ialloc_btree.c
> +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
> @@ -365,9 +365,11 @@ xfs_inobt_init_cursor(
>  	if (btnum == XFS_BTNUM_INO) {
>  		cur->bc_nlevels = be32_to_cpu(agi->agi_level);
>  		cur->bc_ops = &xfs_inobt_ops;
> +		cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_ibt_2);
>  	} else {
>  		cur->bc_nlevels = be32_to_cpu(agi->agi_free_level);
>  		cur->bc_ops = &xfs_finobt_ops;
> +		cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_fibt_2);
>  	}
>  
>  	cur->bc_blocklog = mp->m_sb.sb_blocklog;
> diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
> index 17b8eeb..a749d3b 100644
> --- a/fs/xfs/libxfs/xfs_rmap_btree.c
> +++ b/fs/xfs/libxfs/xfs_rmap_btree.c
> @@ -483,6 +483,7 @@ xfs_rmapbt_init_cursor(
>  	cur->bc_blocklog = mp->m_sb.sb_blocklog;
>  	cur->bc_ops = &xfs_rmapbt_ops;
>  	cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
> +	cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_rmap_2);
>  
>  	cur->bc_private.a.agbp = agbp;
>  	cur->bc_private.a.agno = agno;
> diff --git a/fs/xfs/xfs_stats.c b/fs/xfs/xfs_stats.c
> index 6e812fe0..6e021a7 100644
> --- a/fs/xfs/xfs_stats.c
> +++ b/fs/xfs/xfs_stats.c
> @@ -79,9 +79,9 @@ int xfs_stats_format(struct xfsstats __percpu *stats, char *buf)
>  	}
>  	/* extra precision counters */
>  	for_each_possible_cpu(i) {
> -		xs_xstrat_bytes += per_cpu_ptr(stats, i)->xs_xstrat_bytes;
> -		xs_write_bytes += per_cpu_ptr(stats, i)->xs_write_bytes;
> -		xs_read_bytes += per_cpu_ptr(stats, i)->xs_read_bytes;
> +		xs_xstrat_bytes += per_cpu_ptr(stats, i)->s.xs_xstrat_bytes;
> +		xs_write_bytes += per_cpu_ptr(stats, i)->s.xs_write_bytes;
> +		xs_read_bytes += per_cpu_ptr(stats, i)->s.xs_read_bytes;
>  	}
>  
>  	len += snprintf(buf + len, PATH_MAX-len, "xpc %Lu %Lu %Lu\n",
> @@ -105,9 +105,9 @@ void xfs_stats_clearall(struct xfsstats __percpu *stats)
>  	for_each_possible_cpu(c) {
>  		preempt_disable();
>  		/* save vn_active, it's a universal truth! */
> -		vn_active = per_cpu_ptr(stats, c)->vn_active;
> +		vn_active = per_cpu_ptr(stats, c)->s.vn_active;
>  		memset(per_cpu_ptr(stats, c), 0, sizeof(*stats));
> -		per_cpu_ptr(stats, c)->vn_active = vn_active;
> +		per_cpu_ptr(stats, c)->s.vn_active = vn_active;
>  		preempt_enable();
>  	}
>  }
> diff --git a/fs/xfs/xfs_stats.h b/fs/xfs/xfs_stats.h
> index 657865f..7a57c01 100644
> --- a/fs/xfs/xfs_stats.h
> +++ b/fs/xfs/xfs_stats.h
> @@ -21,10 +21,30 @@
>  
>  #include <linux/percpu.h>
>  
> +enum {
> +	__XBTS_lookup = 0,
> +	__XBTS_compare = 1,
> +	__XBTS_insrec = 2,
> +	__XBTS_delrec = 3,
> +	__XBTS_newroot = 4,
> +	__XBTS_killroot = 5,
> +	__XBTS_increment = 6,
> +	__XBTS_decrement = 7,
> +	__XBTS_lshift = 8,
> +	__XBTS_rshift = 9,
> +	__XBTS_split = 10,
> +	__XBTS_join = 11,
> +	__XBTS_alloc = 12,
> +	__XBTS_free = 13,
> +	__XBTS_moves = 14,
> +
> +	__XBTS_MAX = 15,
> +};
> +
>  /*
>   * XFS global statistics
>   */
> -struct xfsstats {
> +struct __xfsstats {
>  # define XFSSTAT_END_EXTENT_ALLOC	4
>  	__uint32_t		xs_allocx;
>  	__uint32_t		xs_allocb;
> @@ -117,102 +137,18 @@ struct xfsstats {
>  	__uint32_t		xb_page_found;
>  	__uint32_t		xb_get_read;
>  /* Version 2 btree counters */
> -#define XFSSTAT_END_ABTB_V2		(XFSSTAT_END_BUF+15)
> -	__uint32_t		xs_abtb_2_lookup;
> -	__uint32_t		xs_abtb_2_compare;
> -	__uint32_t		xs_abtb_2_insrec;
> -	__uint32_t		xs_abtb_2_delrec;
> -	__uint32_t		xs_abtb_2_newroot;
> -	__uint32_t		xs_abtb_2_killroot;
> -	__uint32_t		xs_abtb_2_increment;
> -	__uint32_t		xs_abtb_2_decrement;
> -	__uint32_t		xs_abtb_2_lshift;
> -	__uint32_t		xs_abtb_2_rshift;
> -	__uint32_t		xs_abtb_2_split;
> -	__uint32_t		xs_abtb_2_join;
> -	__uint32_t		xs_abtb_2_alloc;
> -	__uint32_t		xs_abtb_2_free;
> -	__uint32_t		xs_abtb_2_moves;
> -#define XFSSTAT_END_ABTC_V2		(XFSSTAT_END_ABTB_V2+15)
> -	__uint32_t		xs_abtc_2_lookup;
> -	__uint32_t		xs_abtc_2_compare;
> -	__uint32_t		xs_abtc_2_insrec;
> -	__uint32_t		xs_abtc_2_delrec;
> -	__uint32_t		xs_abtc_2_newroot;
> -	__uint32_t		xs_abtc_2_killroot;
> -	__uint32_t		xs_abtc_2_increment;
> -	__uint32_t		xs_abtc_2_decrement;
> -	__uint32_t		xs_abtc_2_lshift;
> -	__uint32_t		xs_abtc_2_rshift;
> -	__uint32_t		xs_abtc_2_split;
> -	__uint32_t		xs_abtc_2_join;
> -	__uint32_t		xs_abtc_2_alloc;
> -	__uint32_t		xs_abtc_2_free;
> -	__uint32_t		xs_abtc_2_moves;
> -#define XFSSTAT_END_BMBT_V2		(XFSSTAT_END_ABTC_V2+15)
> -	__uint32_t		xs_bmbt_2_lookup;
> -	__uint32_t		xs_bmbt_2_compare;
> -	__uint32_t		xs_bmbt_2_insrec;
> -	__uint32_t		xs_bmbt_2_delrec;
> -	__uint32_t		xs_bmbt_2_newroot;
> -	__uint32_t		xs_bmbt_2_killroot;
> -	__uint32_t		xs_bmbt_2_increment;
> -	__uint32_t		xs_bmbt_2_decrement;
> -	__uint32_t		xs_bmbt_2_lshift;
> -	__uint32_t		xs_bmbt_2_rshift;
> -	__uint32_t		xs_bmbt_2_split;
> -	__uint32_t		xs_bmbt_2_join;
> -	__uint32_t		xs_bmbt_2_alloc;
> -	__uint32_t		xs_bmbt_2_free;
> -	__uint32_t		xs_bmbt_2_moves;
> -#define XFSSTAT_END_IBT_V2		(XFSSTAT_END_BMBT_V2+15)
> -	__uint32_t		xs_ibt_2_lookup;
> -	__uint32_t		xs_ibt_2_compare;
> -	__uint32_t		xs_ibt_2_insrec;
> -	__uint32_t		xs_ibt_2_delrec;
> -	__uint32_t		xs_ibt_2_newroot;
> -	__uint32_t		xs_ibt_2_killroot;
> -	__uint32_t		xs_ibt_2_increment;
> -	__uint32_t		xs_ibt_2_decrement;
> -	__uint32_t		xs_ibt_2_lshift;
> -	__uint32_t		xs_ibt_2_rshift;
> -	__uint32_t		xs_ibt_2_split;
> -	__uint32_t		xs_ibt_2_join;
> -	__uint32_t		xs_ibt_2_alloc;
> -	__uint32_t		xs_ibt_2_free;
> -	__uint32_t		xs_ibt_2_moves;
> -#define XFSSTAT_END_FIBT_V2		(XFSSTAT_END_IBT_V2+15)
> -	__uint32_t		xs_fibt_2_lookup;
> -	__uint32_t		xs_fibt_2_compare;
> -	__uint32_t		xs_fibt_2_insrec;
> -	__uint32_t		xs_fibt_2_delrec;
> -	__uint32_t		xs_fibt_2_newroot;
> -	__uint32_t		xs_fibt_2_killroot;
> -	__uint32_t		xs_fibt_2_increment;
> -	__uint32_t		xs_fibt_2_decrement;
> -	__uint32_t		xs_fibt_2_lshift;
> -	__uint32_t		xs_fibt_2_rshift;
> -	__uint32_t		xs_fibt_2_split;
> -	__uint32_t		xs_fibt_2_join;
> -	__uint32_t		xs_fibt_2_alloc;
> -	__uint32_t		xs_fibt_2_free;
> -	__uint32_t		xs_fibt_2_moves;
> -#define XFSSTAT_END_RMAP_V2		(XFSSTAT_END_FIBT_V2+15)
> -	__uint32_t		xs_rmap_2_lookup;
> -	__uint32_t		xs_rmap_2_compare;
> -	__uint32_t		xs_rmap_2_insrec;
> -	__uint32_t		xs_rmap_2_delrec;
> -	__uint32_t		xs_rmap_2_newroot;
> -	__uint32_t		xs_rmap_2_killroot;
> -	__uint32_t		xs_rmap_2_increment;
> -	__uint32_t		xs_rmap_2_decrement;
> -	__uint32_t		xs_rmap_2_lshift;
> -	__uint32_t		xs_rmap_2_rshift;
> -	__uint32_t		xs_rmap_2_split;
> -	__uint32_t		xs_rmap_2_join;
> -	__uint32_t		xs_rmap_2_alloc;
> -	__uint32_t		xs_rmap_2_free;
> -	__uint32_t		xs_rmap_2_moves;
> +#define XFSSTAT_END_ABTB_V2		(XFSSTAT_END_BUF+__XBTS_MAX)
> +	__uint32_t		xs_abtb_2[__XBTS_MAX];
> +#define XFSSTAT_END_ABTC_V2		(XFSSTAT_END_ABTB_V2+__XBTS_MAX)
> +	__uint32_t		xs_abtc_2[__XBTS_MAX];
> +#define XFSSTAT_END_BMBT_V2		(XFSSTAT_END_ABTC_V2+__XBTS_MAX)
> +	__uint32_t		xs_bmbt_2[__XBTS_MAX];
> +#define XFSSTAT_END_IBT_V2		(XFSSTAT_END_BMBT_V2+__XBTS_MAX)
> +	__uint32_t		xs_ibt_2[__XBTS_MAX];
> +#define XFSSTAT_END_FIBT_V2		(XFSSTAT_END_IBT_V2+__XBTS_MAX)
> +	__uint32_t		xs_fibt_2[__XBTS_MAX];
> +#define XFSSTAT_END_RMAP_V2		(XFSSTAT_END_FIBT_V2+__XBTS_MAX)
> +	__uint32_t		xs_rmap_2[__XBTS_MAX];

Are you planning to merge this before or after the refcount btree?

>  #define XFSSTAT_END_XQMSTAT		(XFSSTAT_END_RMAP_V2+6)
>  	__uint32_t		xs_qm_dqreclaims;
>  	__uint32_t		xs_qm_dqreclaim_misses;
> @@ -229,26 +165,58 @@ struct xfsstats {
>  	__uint64_t		xs_read_bytes;
>  };
>  
> +struct xfsstats {
> +	union {
> +		struct __xfsstats	s;
> +		uint32_t		a[XFSSTAT_END_XQMSTAT];
> +	};

/me wonders if there ought to be a build time check to make sure that
these two are really the same size?  They look all right as is, but
I can see myself forgetting to change something and screwing it up. :(

> +};
> +
> +/*
> + * simple wrapper for getting the array index of s struct member offset
> + */
> +#define XFS_STATS_CALC_INDEX(member)	\
> +	(offsetof(struct __xfsstats, member) / (int)sizeof(__uint32_t))
> +
> +
>  int xfs_stats_format(struct xfsstats __percpu *stats, char *buf);
>  void xfs_stats_clearall(struct xfsstats __percpu *stats);
>  extern struct xstats xfsstats;
>  
>  #define XFS_STATS_INC(mp, v)					\
>  do {								\
> -	per_cpu_ptr(xfsstats.xs_stats, current_cpu())->v++;	\
> -	per_cpu_ptr(mp->m_stats.xs_stats, current_cpu())->v++;	\
> +	per_cpu_ptr(xfsstats.xs_stats, current_cpu())->s.v++;	\
> +	per_cpu_ptr(mp->m_stats.xs_stats, current_cpu())->s.v++;	\
>  } while (0)
>  
>  #define XFS_STATS_DEC(mp, v)					\
>  do {								\
> -	per_cpu_ptr(xfsstats.xs_stats, current_cpu())->v--;	\
> -	per_cpu_ptr(mp->m_stats.xs_stats, current_cpu())->v--;	\
> +	per_cpu_ptr(xfsstats.xs_stats, current_cpu())->s.v--;	\
> +	per_cpu_ptr(mp->m_stats.xs_stats, current_cpu())->s.v--;	\
>  } while (0)
>  
>  #define XFS_STATS_ADD(mp, v, inc)					\
>  do {									\
> -	per_cpu_ptr(xfsstats.xs_stats, current_cpu())->v += (inc);	\
> -	per_cpu_ptr(mp->m_stats.xs_stats, current_cpu())->v += (inc);	\
> +	per_cpu_ptr(xfsstats.xs_stats, current_cpu())->s.v += (inc);	\
> +	per_cpu_ptr(mp->m_stats.xs_stats, current_cpu())->s.v += (inc);	\
> +} while (0)
> +
> +#define XFS_STATS_INC_OFF(mp, off)				\
> +do {								\
> +	per_cpu_ptr(xfsstats.xs_stats, current_cpu())->a[off]++;	\
> +	per_cpu_ptr(mp->m_stats.xs_stats, current_cpu())->a[off]++;	\
> +} while (0)
> +
> +#define XFS_STATS_DEC_OFF(mp, off)					\
> +do {								\
> +	per_cpu_ptr(xfsstats.xs_stats, current_cpu())->a[off];	\
> +	per_cpu_ptr(mp->m_stats.xs_stats, current_cpu())->a[off];	\
> +} while (0)
> +
> +#define XFS_STATS_ADD_OFF(mp, off, inc)					\
> +do {									\
> +	per_cpu_ptr(xfsstats.xs_stats, current_cpu())->a[off] += (inc);	\
> +	per_cpu_ptr(mp->m_stats.xs_stats, current_cpu())->a[off] += (inc);	\
>  } while (0)
>  
>  #if defined(CONFIG_PROC_FS)

Looks more or less ok to me....

--D

> -- 
> 2.8.0.rc3
> 
> _______________________________________________
> xfs mailing list
> xfs@xxxxxxxxxxx
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs



[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux