为什么我不能写超过 2GB?
Why can't I write more than 2GB?
我正在使用这段代码来测量我电脑的写入带宽。该程序需要两个参数,我们要写入的文件的名称和 MB 的数量。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
int main(int argc, char *argv[]) {
struct timeval tv0, tv1;
int chunkSize = 128, res;
char str[chunkSize];
if (argc != 3)
perror("Usage: file_name Mb.");
int megabytes = atoi(argv[2]);
int sizeWrite = megabytes*1024*1024;
int sizeWriteAux = sizeWrite;
FILE * fp;
fp = fopen (argv[1], "w+");
res = gettimeofday(&tv0, NULL);
if (res < 0) {
perror ("gettimeofday");
}
while (sizeWriteAux > 0) {
fwrite(str , 1 , chunkSize , fp );
sizeWriteAux -= chunkSize;
}
res = gettimeofday(&tv1, NULL);
if (res < 0) {
perror ("gettimeofday");
}
fclose(fp);
double secs = (((double)tv1.tv_sec*1000000.0 + (double)tv1.tv_usec) - ((double)tv0.tv_sec*1000000.0 + (double)tv0.tv_usec))/1000000.0;
printf("Time: %f \n", secs);
double x = sizeWrite/secs;
double y = megabytes/secs;
printf("Bandwith: %f bytes x sec \n", x);
printf("Bandwith: %f Mbytes x sec \n", y);
return(0);
}
该程序在最大 2047 MB 时可以正常运行,但从 2048 MB 开始它不会写入任何内容并导致无限带宽而不会返回任何错误。
我 运行 这个程序在 VirtualBox 的 Ubuntu 20 上,有 12GB RAM 和 10GB 可用磁盘内存。
有人知道为什么会这样吗?
带宽 x
和 y
分别是 -inf 和 inf 由于不足和溢出,因为 sizeWrite
是正的,megabytes
是负的,而 secs
接近0
。兆字节由于 sizeWrite = megabytes*1024*1024
中的溢出而为负,因为对于 sizeof(int) == 4,值大于 2^31 - 1。secs
接近 0
因为 sizeWriteAux
是负数,因为它被初始化为 megabytes
,这反过来意味着 while 循环根本没有 运行 。第一顺序修复是:
unsigned long sizeWrite = megabytes*1024*1024;
unsigned long sizeWriteAux = sizeWrite;
如果两个参数均未指定,您的程序将崩溃。您通常缺少错误检查。每 fclose(2):
Typically, filesystems do not flush buffers when a file is closed. If you need to be sure that the data is physically stored on the underlying disk, use fsync(2).
您还需要检查 secs 以确保它足够大,从而避免 x
和 y
溢出。当您的值为正时使用无符号类型。
您可能对此感兴趣:
file=...
size=...
block_size=128
time dd if=/dev/zero of=$file bs=$block_size count=$(($size * 1024 * 1024 / $block_size))
您可能会看到 block_size = 4096 * n
的性能提升,其中 n 至少为 1。
int megabytes = atoi(argv[2]);
int sizeWrite = megabytes*1024*1024;
int sizeWriteAux = sizeWrite;
您正在使用 int
。看来,在您的系统上 sizeof(int) == 4 (bytes)
。
由于 int
是 signed
并且一位用于符号,因此您只能使用 31 位。
2^31 = 2147483648 (2G)
如果您会使用 unsigned int
,那么
2^32 = 4294967296 (4G)
一点点改变会有什么不同,对吗?
现在想象一下,您会使用 (long) long int
,即 64 位。
并且您应该注意底层文件系统的文件大小限制。例如,Fat 的文件最大限制为 2G。
我正在使用这段代码来测量我电脑的写入带宽。该程序需要两个参数,我们要写入的文件的名称和 MB 的数量。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
int main(int argc, char *argv[]) {
struct timeval tv0, tv1;
int chunkSize = 128, res;
char str[chunkSize];
if (argc != 3)
perror("Usage: file_name Mb.");
int megabytes = atoi(argv[2]);
int sizeWrite = megabytes*1024*1024;
int sizeWriteAux = sizeWrite;
FILE * fp;
fp = fopen (argv[1], "w+");
res = gettimeofday(&tv0, NULL);
if (res < 0) {
perror ("gettimeofday");
}
while (sizeWriteAux > 0) {
fwrite(str , 1 , chunkSize , fp );
sizeWriteAux -= chunkSize;
}
res = gettimeofday(&tv1, NULL);
if (res < 0) {
perror ("gettimeofday");
}
fclose(fp);
double secs = (((double)tv1.tv_sec*1000000.0 + (double)tv1.tv_usec) - ((double)tv0.tv_sec*1000000.0 + (double)tv0.tv_usec))/1000000.0;
printf("Time: %f \n", secs);
double x = sizeWrite/secs;
double y = megabytes/secs;
printf("Bandwith: %f bytes x sec \n", x);
printf("Bandwith: %f Mbytes x sec \n", y);
return(0);
}
该程序在最大 2047 MB 时可以正常运行,但从 2048 MB 开始它不会写入任何内容并导致无限带宽而不会返回任何错误。
我 运行 这个程序在 VirtualBox 的 Ubuntu 20 上,有 12GB RAM 和 10GB 可用磁盘内存。
有人知道为什么会这样吗?
带宽 x
和 y
分别是 -inf 和 inf 由于不足和溢出,因为 sizeWrite
是正的,megabytes
是负的,而 secs
接近0
。兆字节由于 sizeWrite = megabytes*1024*1024
中的溢出而为负,因为对于 sizeof(int) == 4,值大于 2^31 - 1。secs
接近 0
因为 sizeWriteAux
是负数,因为它被初始化为 megabytes
,这反过来意味着 while 循环根本没有 运行 。第一顺序修复是:
unsigned long sizeWrite = megabytes*1024*1024;
unsigned long sizeWriteAux = sizeWrite;
如果两个参数均未指定,您的程序将崩溃。您通常缺少错误检查。每 fclose(2):
Typically, filesystems do not flush buffers when a file is closed. If you need to be sure that the data is physically stored on the underlying disk, use fsync(2).
您还需要检查 secs 以确保它足够大,从而避免 x
和 y
溢出。当您的值为正时使用无符号类型。
您可能对此感兴趣:
file=...
size=...
block_size=128
time dd if=/dev/zero of=$file bs=$block_size count=$(($size * 1024 * 1024 / $block_size))
您可能会看到 block_size = 4096 * n
的性能提升,其中 n 至少为 1。
int megabytes = atoi(argv[2]);
int sizeWrite = megabytes*1024*1024;
int sizeWriteAux = sizeWrite;
您正在使用 int
。看来,在您的系统上 sizeof(int) == 4 (bytes)
。
由于 int
是 signed
并且一位用于符号,因此您只能使用 31 位。
2^31 = 2147483648 (2G)
如果您会使用 unsigned int
,那么
2^32 = 4294967296 (4G)
一点点改变会有什么不同,对吗?
现在想象一下,您会使用 (long) long int
,即 64 位。
并且您应该注意底层文件系统的文件大小限制。例如,Fat 的文件最大限制为 2G。