Skip to content

Commit 71644df

Browse files
author
Jaegeuk Kim
committed
f2fs: add block_age-based extent cache
This patch introduces a runtime hot/cold data separation method for f2fs, in order to improve the accuracy for data temperature classification, reduce the garbage collection overhead after long-term data updates. Enhanced hot/cold data separation can record data block update frequency as "age" of the extent per inode, and take use of the age info to indicate better temperature type for data block allocation: - It records total data blocks allocated since mount; - When file extent has been updated, it calculate the count of data blocks allocated since last update as the age of the extent; - Before the data block allocated, it searches for the age info and chooses the suitable segment for allocation. Test and result: - Prepare: create about 30000 files * 3% for cold files (with cold file extension like .apk, from 3M to 10M) * 50% for warm files (with random file extension like .FcDxq, from 1K to 4M) * 47% for hot files (with hot file extension like .db, from 1K to 256K) - create(5%)/random update(90%)/delete(5%) the files * total write amount is about 70G * fsync will be called for .db files, and buffered write will be used for other files The storage of test device is large enough(128G) so that it will not switch to SSR mode during the test. Benefit: dirty segment count increment reduce about 14% - before: Dirty +21110 - after: Dirty +18286 Signed-off-by: qixiaoyu1 <[email protected]> Signed-off-by: xiongping1 <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 72840cc commit 71644df

File tree

14 files changed

+430
-10
lines changed

14 files changed

+430
-10
lines changed

Documentation/ABI/testing/sysfs-fs-f2fs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,3 +655,17 @@ Description: When space utilization exceeds this, do background DISCARD aggressi
655655
Does DISCARD forcibly in a period of given min_discard_issue_time when the number
656656
of discards is not 0 and set discard granularity to 1.
657657
Default: 80
658+
659+
What: /sys/fs/f2fs/<disk>/hot_data_age_threshold
660+
Date: November 2022
661+
Contact: "Ping Xiong" <[email protected]>
662+
Description: When DATA SEPARATION is on, it controls the age threshold to indicate
663+
the data blocks as hot. By default it was initialized as 262144 blocks
664+
(equals to 1GB).
665+
666+
What: /sys/fs/f2fs/<disk>/warm_data_age_threshold
667+
Date: November 2022
668+
Contact: "Ping Xiong" <[email protected]>
669+
Description: When DATA SEPARATION is on, it controls the age threshold to indicate
670+
the data blocks as warm. By default it was initialized as 2621440 blocks
671+
(equals to 10GB).

Documentation/filesystems/f2fs.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,10 @@ memory=%s Control memory mode. This supports "normal" and "low" modes.
347347
Because of the nature of low memory devices, in this mode, f2fs
348348
will try to save memory sometimes by sacrificing performance.
349349
"normal" mode is the default mode and same as before.
350+
age_extent_cache Enable an age extent cache based on rb-tree. It records
351+
data block update frequency of the extent per inode, in
352+
order to provide better temperature hints for data block
353+
allocation.
350354
======================== ============================================================
351355

352356
Debugfs Entries

fs/f2fs/debug.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ static void update_general_status(struct f2fs_sb_info *sbi)
8888
si->hit_largest = atomic64_read(&sbi->read_hit_largest);
8989
si->hit_total[EX_READ] += si->hit_largest;
9090

91+
/* block age extent_cache only */
92+
si->allocated_data_blocks = atomic64_read(&sbi->allocated_data_blocks);
93+
9194
/* validation check of the segment numbers */
9295
si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
9396
si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
@@ -516,6 +519,22 @@ static int stat_show(struct seq_file *s, void *v)
516519
seq_printf(s, " - Inner Struct Count: tree: %d(%d), node: %d\n",
517520
si->ext_tree[EX_READ], si->zombie_tree[EX_READ],
518521
si->ext_node[EX_READ]);
522+
seq_puts(s, "\nExtent Cache (Block Age):\n");
523+
seq_printf(s, " - Allocated Data Blocks: %llu\n",
524+
si->allocated_data_blocks);
525+
seq_printf(s, " - Hit Count: L1:%llu L2:%llu\n",
526+
si->hit_cached[EX_BLOCK_AGE],
527+
si->hit_rbtree[EX_BLOCK_AGE]);
528+
seq_printf(s, " - Hit Ratio: %llu%% (%llu / %llu)\n",
529+
!si->total_ext[EX_BLOCK_AGE] ? 0 :
530+
div64_u64(si->hit_total[EX_BLOCK_AGE] * 100,
531+
si->total_ext[EX_BLOCK_AGE]),
532+
si->hit_total[EX_BLOCK_AGE],
533+
si->total_ext[EX_BLOCK_AGE]);
534+
seq_printf(s, " - Inner Struct Count: tree: %d(%d), node: %d\n",
535+
si->ext_tree[EX_BLOCK_AGE],
536+
si->zombie_tree[EX_BLOCK_AGE],
537+
si->ext_node[EX_BLOCK_AGE]);
519538
seq_puts(s, "\nBalancing F2FS Async:\n");
520539
seq_printf(s, " - DIO (R: %4d, W: %4d)\n",
521540
si->nr_dio_read, si->nr_dio_write);
@@ -586,6 +605,8 @@ static int stat_show(struct seq_file *s, void *v)
586605
si->cache_mem >> 10);
587606
seq_printf(s, " - read extent cache: %llu KB\n",
588607
si->ext_mem[EX_READ] >> 10);
608+
seq_printf(s, " - block age extent cache: %llu KB\n",
609+
si->ext_mem[EX_BLOCK_AGE] >> 10);
589610
seq_printf(s, " - paged : %llu KB\n",
590611
si->page_mem >> 10);
591612
}

0 commit comments

Comments
 (0)