C代码测量Linux中的磁盘写入时间并处理RAM缓冲

Posted

技术标签:

【中文标题】C代码测量Linux中的磁盘写入时间并处理RAM缓冲【英文标题】:C code measuring disk write time in linux and dealing with RAM buffering 【发布时间】:2016-08-12 01:48:28 【问题描述】:

参考http://www.linuxatemyram.com/,它描述了磁盘 i/o 如何在内存中缓冲。我想考虑这一点,并实际撤消它,以测量将不同数量的数据写入文件所需的时间。 我要做的是根据两种情况的 i/o 了解运行时间:

    通过mount -t tmpfs -o size=500g tmpfs /ramdisk作为ramdisk安装到内存中 将数据写入/scratch/,这是一个格式化为 EXT3 或 XFS 的 900GB 希捷 sas 硬盘

我的程序在将文件写入硬盘时非常快,我确信这是因为 linux 操作系统正在缓冲 RAM 中的数据,从而使磁盘 i/o 透明......因为在我的程序完成后,如果在提示我执行rm temp_speed*,这需要一分钟或更长时间。

例如,如果程序正在写入 10gb,则完成写入 ramdisk 需要 7 秒,完成写入 /scratch 需要 20 秒。但是我可以在写入 ramdisk 后执行 rm temp* 并在 1-3 秒内完成,而如果它是从头开始的,则删除命令需要 90 多秒才能完成。

任何人都知道我如何编写下面的程序来知道磁盘 i/o 何时在程序中完全完成?谢谢。

请注意,如果您尝试运行此代码,您可能会迅速填满您的硬盘驱动器和/或内存并导致系统崩溃。

# include <stdio.h>
# include <stdlib.h>
# include <time.h>

# define MAX_F  256

/* WARNING: running this code you risk quickly filling up */
/*          your hard drive and/or memory and crashing your system.  */

/* compile with -O0  no optimization */

long int get_time ( void )

   long int t;

   t = (long int) time( NULL );

   return( t );


void diff_time ( long int *start, long int *finish )

   time_t s, e;
   long int diff;
   long int h = 0, m = 0;

   s = (time_t) *start;
   e = (time_t) *finish;

   diff = (long int) difftime( e, s );

   h = diff / 3600;

   diff -= ( h * 3600 );

   m = diff / 60;

   diff -= ( m * 60 );

   printf(" problem runtime (h:m:s) = %02ld:%02ld:%02ld\n", h, m, diff );
   printf("\n");


int main ( int argc, char *argv[] )

    FILE *fp[MAX_F];
    char fname[MAX_F][64];
    long int a, i, amount, num_times, num_files;
    long int maxfilesize;
    long int start_time, end_time;
    double ff[512];     /* 512 doubles = 4096 = 4k worth of data */


    if ( argc != 3 )
    
       printf("\n   usage: readwrite_speed  <total amount in gb> <max file size in gb>\n\n");
       exit( 0 );
    

    system( "date" );

    amount = atol( argv[1] );
    maxfilesize = atol( argv[2] );

    if ( maxfilesize > amount )
       maxfilesize = amount;

    num_files = amount / maxfilesize;

    if ( num_files > MAX_F )
    
       printf("\n   increase max # files abouve %d\n\n", MAX_F );
       exit( 0 );
    

    num_times = ( amount * 1024 * 1024 * 1024 ) / 4096;

    num_times /= num_files;

    printf("\n");
    printf("   amount = %ldgb, num_times = %ld, num_files = %ld\n", amount, num_times, num_files );

    printf("\n");

    for ( i = 0; i < num_files; i++ )
       sprintf( fname[i], "temp_speed%03d", i );

    start_time = get_time();

    for ( i = 0; i < num_files; i++ )
    
       fp[i] = fopen( fname[i], "wb" );
       if ( fp[i] == NULL )
           printf("   can't write binary %s\n", fname[i] );
    

    for ( i = 0; i < 512; i++ )
       ff[i] = rand() / RAND_MAX;

    /* 1 gb = 262,144 times writing 4096 bytes */

    for ( a = 0; a < num_times; a++ )
    
       for ( i = 0; i < num_files; i++ )
       
          fwrite( ff, sizeof( double ), 512, fp[i] );
          fflush( fp[i] );
       
    

    for ( i = 0; i < num_files; i++ )
       fclose( fp[i] );

    end_time = get_time();

    diff_time( &start_time, &end_time );

    system( "date" );

【问题讨论】:

首先,不要使用fopen()fwrite()。使用open()write()。这样就不需要fflush() 的开销,并且可以使用O_DIRECT 绕过页面缓存。有关使用O_DIRECT 的详细信息,请参阅open.2 man page - 并注意它们。 Linux 上的 Direct IO 是一个挑剔的野兽。最后,您要测量什么?您的磁盘可以多快地移动数据,或者它可以支持多少个单独的 IO 操作/秒?这些不是一回事,尤其是对于物理的旋转磁盘。 寻找一种简单而合理的方法来量化和显示任何人(非计算机头脑的人)在运行程序时磁盘 i/o 的影响以及该程序是否从本地 ram 或 ramdisk 访问数据,到本地硬盘,到网络共享存储,等等。并显示必须担心 1 GB 或更少的数据与 500 GB 或更多数据之间的差异以及所涉及的时间尺度。 我正在处理一些具有 256gb 和 512gb 内存的服务器,只有一个 300gb 和/或 600gb 2.5" 硬盘。linux os (SLES11.4) 非常擅长使用内存以弥补缓慢的磁盘写入,这就是阻止我获得将 N GB 写入我的旋转硬盘驱动器所需的真实经过时间的原因。 【参考方案1】:

首先,看here。 您无法 100% 保证数据在磁盘上。 您可以使用 fsync 告诉内核将数据刷新到磁盘。但是磁盘和磁盘控制器都有自己的缓存,所以即使是内核也不能总是知道它什么时候 100% 完成了。

【讨论】:

以上是关于C代码测量Linux中的磁盘写入时间并处理RAM缓冲的主要内容,如果未能解决你的问题,请参考以下文章

apache 2.4磁盘缓存不写入缓存根

刷新缓存区方式和刷新内存到磁盘方式总结。

当运行时修改写入名称节点中的编辑日志文件时,编辑日志文件是在 RAM 还是本地磁盘上更新

哪些内存页面分配给 Linux RAM 磁盘中的文件

GCP Dataflow 中的 RAM 磁盘 - 有可能吗?

使用 C 测量内存写入带宽