Hello Matthew, after some peripeties, I was able to bisect down to a regression in truncate performance caused by commit 69b6c1319b6 "mm: Convert truncate to XArray". The initial benchmark that indicated the regression was a bonnie++ file delete test (some 4-5% regression). It is however much easier (and faster!) to see the regression with the attached benchmark. With it I can see about 10% regression on my test machine: Average of 10 runs, time in us. COMMIT AVG STDDEV a97e7904c0 1431256.500000 1489.361759 69b6c1319b 1566944.000000 2252.692877 The benchmark has to be run so that the total file size is about 2x the memory size (as the regression seems to be in trucating existing workingset entries). So on my test machine with 32 GB of RAM I run it like: # This prepares the environment mkfs.xfs -f /dev/sdb1 mount -t xfs /dev/sdb1 /mnt ./trunc-bench /mnt/file 64 1 # This does the truncation ./trunc-bench /mnt/file 64 2 I've gathered also perf profiles but from the first look they don't show anything surprising besides xas_load() and xas_store() taking up more time than original counterparts did. I'll try to dig more into this but any idea is appreciated. My test machine is 8 CPU Intel(R) Xeon(R) CPU E3-1240 v5 @ 3.50GHz. Honza -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR
#include <stdio.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <stdlib.h> #include <sys/time.h> #define COUNT 1024 #define BUFSIZE (1024*1024) char *buf; void read_file(int fd) { int i; if (ftruncate(fd, BUFSIZE*COUNT) < 0) { perror("truncate"); exit(1); } for (i = 0; i < COUNT; i++) { if (read(fd, buf, BUFSIZE) != BUFSIZE) { perror("read"); exit(1); } } } int main(int argc, char **argv) { int fd; int fcount, i, stages; char fname[128]; struct timeval start, end; if (argc != 4) { fprintf(stderr, "Usage: trunc-bench <file> <file-count> <stages>\n"); return 1; } fcount = strtol(argv[2], NULL, 0); stages = strtol(argv[3], NULL, 0); buf = malloc(BUFSIZE); if (!buf) { fprintf(stderr, "Cannot allocate write buffer.\n"); return 1; } memset(buf, 'a', BUFSIZE); if (stages & 1) { fprintf(stderr, "Creating files...\n"); for (i = 0; i < fcount; i++ ) { sprintf(fname, "%s%d", argv[1], i); fd = open(fname, O_RDWR | O_TRUNC | O_CREAT, 0644); if (fd < 0) { perror("open"); return 1; } read_file(fd); close(fd); } } if (stages & 2) { fprintf(stderr, "Removing files...\n"); gettimeofday(&start, NULL); for (i = 0; i < fcount; i++ ) { sprintf(fname, "%s%d", argv[1], i); truncate(fname, 0); } gettimeofday(&end, NULL); printf("%lu us\n", (end.tv_sec - start.tv_sec) * 1000000UL + (end.tv_usec - start.tv_usec)); } fprintf(stderr, "Done.\n"); return 0; }