如果我有文本文件(textfile),其中包含一行文本,而Perl文件(perlscript)为
#!/usr/bin/perl
use strict;
use warnings;
my $var;
$var.=$_ while (<>) ;
print $var;命令在终端中运行
cat ./textfile | ./perlscript | ./perlscript | ./perlscript如果我在一个1kb的文本文件上运行上面的代码,而不是程序栈等,我是否使用了4Kb的内存?或者当我从STDIN中提取时,我是否释放了那个内存,因此,我只会使用1KB?
换句话说,从STDIN复制到一个变量是否在内存使用上是有效中立的?还是增加一倍的内存消耗?
发布于 2017-08-03 00:25:33
你已经得到了一个很好的答案,但我对我的猜测并不满意,所以我决定测试我的假设。
我制作了一个简单的C++程序,名为streamstream,它只需要使用STDIN并以1024字节的块将其写入STDOUT。看起来是这样的:
#include <stdio.h>
int main()
{
const int BUF_SIZE = 1024;
unsigned char* buf = new unsigned char[BUF_SIZE];
size_t read = fread(buf, 1, BUF_SIZE, stdin);
while(read > 0)
{
fwrite(buf, 1, read, stdout);
read = fread(buf, 1, BUF_SIZE, stdin);
}
delete buf;
}为了测试程序是如何使用内存的,我使用valgrind运行它,同时将输出从一个连接到另一个,如下所示:
cat onetwoeightk | valgrind --tool=massif ./streamstream | valgrind --tool=massif ./streamstream | valgrind --tool=massif ./streamstream | hexdump...where onetwoeightk只是一个128 of的随机字节文件。然后,我在massif输出上使用了ms_print工具来帮助解释。显然,程序本身和它的堆的开销很大,但它的起始值大约为80‘s,但从没有超过这一点,因为它一次只喝一’s的STDIN。
数据一次从进程传递到处理1 at。我们的总体内存使用量将达到1KB*处理该流的程序的实例数。
现在让我们来做您的perl程序正在做的事情--我将读取整个流(每次增长我的缓冲区),然后将其全部写入STDOUT。然后我再检查一下瓦朗的产量。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
const int BUF_INCREMENT = 1024;
unsigned char* inbuf = (unsigned char*)malloc(BUF_INCREMENT);
unsigned char* buf = NULL;
unsigned int bufsize = 0;
size_t read = fread(inbuf, 1, BUF_INCREMENT, stdin);
while(read > 0)
{
bufsize += read;
buf = (unsigned char *)realloc(buf, bufsize);
memcpy(buf + bufsize - read, inbuf, read);
read = fread(inbuf, 1, BUF_INCREMENT, stdin);
}
fwrite(buf, 1, bufsize, stdout);
free(inbuf);
free(buf);
}不足为奇的是,在程序执行过程中,内存使用量上升到128 of以上。
KB
137.0^ :#
| ::#
| ::::#
| :@:::#
| :::@:::#
| :::::@:::#
| :@:::::@:::#
| :@:@:::::@:::#
| ::@:@:::::@:::#
| :@::@:@:::::@:::#
| :@:@::@:@:::::@:::#
| @::@:@::@:@:::::@:::#
| ::@::@:@::@:@:::::@:::#
| :@::@::@:@::@:@:::::@:::#
| @:@::@::@:@::@:@:::::@:::#
| ::@:@::@::@:@::@:@:::::@:::#
| :@::@:@::@::@:@::@:@:::::@:::#
| @::@::@:@::@::@:@::@:@:::::@:::#
| ::@::@::@:@::@::@:@::@:@:::::@:::#
| ::::@::@::@:@::@::@:@::@:@:::::@:::#
0 +----------------------------------------------------------------------->ki
0 210.9但问题是,由于这种方法,内存的总使用量是多少?我找不到一个很好的工具来测量一组交互进程的内存占用时间。ps在这里似乎不够精确,即使我插入了一堆睡眠。但是我们可以解决这个问题:128 at的缓冲区只有在程序执行结束时,在写入流之后才被释放。但是,在编写流时,程序的另一个实例构建了自己的128 is缓冲区。因此,我们知道我们的内存使用量将攀升到2x128 we。但是,通过链接更多的程序实例,它不会上升到3x或4x128 or,因为我们的实例释放了它们的内存,并且在完成对STDOUT的写入之后,它们就会关闭。
发布于 2017-08-02 22:25:46
更像是2kB,但是一个1kB的文件不是一个很好的例子,因为您的读取缓冲区可能比这个要大。让我们把文件改为1GB。那么您的峰值内存使用量可能在2GB左右,外加一些开销。cat使用的内存可以忽略不计,只需调整输入到其输出。第一个perl进程必须读取所有这些输入,并使用1GB (加一点点)将其存储在$var中。然后,它开始将它写到第二个,后者将把它存储到它自己的私有$var中,也使用1GB (加一点),所以我们最多可以使用2GB。当第一个perl进程完成写入时,它就会退出,从而关闭它的stdout,从而导致第二个perl进程在stdin上获得EOF,这就是导致while(<>)循环终止和第二个perl进程开始写入的原因。此时,第三个perl进程开始使用另一个1GB读取并存储到它自己的$var中,但是第一个已经没有了,所以我们仍然在2GB的附近。然后,第二个perl进程结束,第三个进程开始写入stdout,并退出自身。
https://stackoverflow.com/questions/45471910
复制相似问题