On Tue, Jun 17, 2025 at 2:33 PM Chao Yu <c...@kernel.org> wrote:
>
> On 6/14/25 07:05, Daniel Lee wrote:
> > A new command 'test_create_perf', has been introduced to measure
> > the performance of creating and deleting many files.
> >
> > Signed-off-by: Daniel Lee <chul...@google.com>
> > ---
> > v2: Rename command and make fsync optional
> > ---
> >  tools/f2fs_io/f2fs_io.c | 139 ++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 139 insertions(+)
> >
> > diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c
> > index 6531b55..6831e78 100644
> > --- a/tools/f2fs_io/f2fs_io.c
> > +++ b/tools/f2fs_io/f2fs_io.c
> > @@ -2092,6 +2092,144 @@ static void do_ftruncate(int argc, char **argv, 
> > const struct cmd_desc *cmd)
> >       exit(0);
> >  }
> >
> > +#define test_create_perf_desc "measure file creation speed"
> > +#define test_create_perf_help                                              
> >   \
> > +"f2fs_io test_create_perf [-s] <dir> <num_files> <size_kb>\n\n"            
> >   \
> > +"Measures file creation and deletion performance.\n"                 \
> > +"  <dir>          The target directory where files will be created.\n"     
> >   \
> > +"  <num_files>    The total number of files to create and delete.\n" \
> > +"  <size_kb>      The size of each file in kb.\n"                    \
> > +"  [-s]           Call fsync() after each file creation to measure\n"
> > +
> > +static void do_test_create_perf(int argc, char **argv, const struct 
> > cmd_desc *cmd)
> > +{
> > +     bool do_fsync = false;
> > +     int opt;
> > +     char *dir;
> > +     int num_files;
> > +     int size_kb;
> > +     char *write_buffer = NULL;
> > +
> > +     while ((opt = getopt(argc, argv, "s")) != -1) {
> > +             switch (opt) {
> > +             case 's':
> > +                     do_fsync = true;
> > +                     break;
> > +             default:
> > +                     fputs(cmd->cmd_help, stderr);
> > +                     exit(1);
> > +             }
> > +     }
> > +
> > +     argc -= optind;
> > +     argv += optind;
> > +
> > +     if (argc != 3) {
> > +             fputs("Excess arguments\n\n", stderr);
> > +             fputs(cmd->cmd_help, stderr);
> > +             exit(1);
> > +     }
> > +
> > +     dir = argv[0];
> > +     num_files = atoi(argv[1]);
> > +     size_kb = atoi(argv[2]);
> > +
> > +     if (num_files <= 0) {
> > +             fprintf(stderr, "Error: Number of files must be positive.\n");
> > +             exit(1);
> > +     }
> > +
> > +     if (size_kb > 0) {
> > +             write_buffer = malloc(size_kb * 1024);
> > +             if (!write_buffer) {
> > +                     perror("Failed to allocate write buffer");
> > +                     exit(1);
> > +             }
> > +             memset(write_buffer, 'a', size_kb * 1024);
> > +     }
> > +
> > +     // Creation Phase
> > +     printf("Starting test: Creating %d files of %dKB each in %s (fsync: 
> > %s)\n",
> > +             num_files, size_kb, dir,
> > +             do_fsync ? "Enabled" : "Disabled");
> > +
> > +     struct timespec create_start, create_end;
> > +
> > +     clock_gettime(CLOCK_MONOTONIC, &create_start);
> > +
> > +     for (int i = 0; i < num_files; i++) {
> > +             char path[1024];
> > +
> > +             snprintf(path, sizeof(path), "%s/test_file_%d", dir, i);
> > +
> > +             int fd = open(path, O_WRONLY | O_CREAT, 0644);
> > +
> > +             if (fd < 0) {
> > +                     perror("Error opening file");
> > +                     continue;
> > +             }
> > +             if (size_kb > 0) {
> > +                     if (write(fd, write_buffer, size_kb * 1024) < 0)
> > +                             perror("Error writing to file");
> > +             }
> > +
> > +             if (do_fsync)
> > +                     fsync(fd);
> > +
> > +             close(fd);
> > +     }
> > +
> > +     clock_gettime(CLOCK_MONOTONIC, &create_end);
> > +
> > +
> > +     // Deletion Phase
> > +     printf("Deleting %d created files...\n", num_files);
> > +
> > +     struct timespec del_start, del_end;
> > +
> > +     clock_gettime(CLOCK_MONOTONIC, &del_start);
> > +
> > +     for (int i = 0; i < num_files; i++) {
> > +             char path[1024];
> > +
> > +             snprintf(path, sizeof(path), "%s/test_file_%d", dir, i);
> > +             if (unlink(path) != 0)
> > +                     perror("Error unlinking file");
> > +     }
> > +     sync();
>
> How about calling sync() or fsync() optionally like we did for creation perf 
> test?
>
> if (do_fsync)
>         fsync(parent_fd); ?
>
> Thanks,

Thanks for the suggestion. I'll make the sync() call optional in the
next version.

>
> > +
> > +     clock_gettime(CLOCK_MONOTONIC, &del_end);
> > +
> > +     long create_seconds = create_end.tv_sec - create_start.tv_sec;
> > +     long create_ns = create_end.tv_nsec - create_start.tv_nsec;
> > +     double create_time_s = (double)create_seconds + (double)create_ns / 
> > 1000000000.0;
> > +     double create_throughput = (create_time_s > 0) ? (num_files / 
> > create_time_s) : 0;
> > +
> > +     long del_seconds = del_end.tv_sec - del_start.tv_sec;
> > +     long del_ns = del_end.tv_nsec - del_start.tv_nsec;
> > +     double del_time_s = (double)del_seconds + (double)del_ns / 
> > 1000000000.0;
> > +     double del_throughput = (del_time_s > 0) ? (num_files / del_time_s) : 
> > 0;
> > +
> > +     
> > printf("Operation,total_files,file_size_kb,total_time_s,throughput_files_per_sec\n");
> > +
> > +     printf("CREATE,%d,%d,%.4f,%.2f\n",
> > +                num_files,
> > +                size_kb,
> > +                create_time_s,
> > +                create_throughput);
> > +
> > +     printf("DELETE,%d,%d,%.4f,%.2f\n",
> > +                num_files,
> > +                size_kb,
> > +                del_time_s,
> > +                del_throughput);
> > +
> > +     if (write_buffer)
> > +             free(write_buffer);
> > +
> > +     exit(0);
> > +}
> > +
> >  #define CMD_HIDDEN   0x0001
> >  #define CMD(name) { #name, do_##name, name##_desc, name##_help, 0 }
> >  #define _CMD(name) { #name, do_##name, NULL, NULL, CMD_HIDDEN }
> > @@ -2140,6 +2278,7 @@ const struct cmd_desc cmd_list[] = {
> >       CMD(get_advise),
> >       CMD(ioprio),
> >       CMD(ftruncate),
> > +     CMD(test_create_perf),
> >       { NULL, NULL, NULL, NULL, 0 }
> >  };
> >
>


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to