首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >读取STDIN时的内存使用情况

读取STDIN时的内存使用情况
EN

Stack Overflow用户
提问于 2017-08-02 22:18:01
回答 2查看 972关注 0票数 1

如果我有文本文件(textfile),其中包含一行文本,而Perl文件(perlscript)为

代码语言:javascript
复制
#!/usr/bin/perl
use strict;
use warnings;
my $var; 
$var.=$_ while (<>) ;
print $var;

命令在终端中运行

代码语言:javascript
复制
cat ./textfile | ./perlscript | ./perlscript | ./perlscript

如果我在一个1kb的文本文件上运行上面的代码,而不是程序栈等,我是否使用了4Kb的内存?或者当我从STDIN中提取时,我是否释放了那个内存,因此,我只会使用1KB?

换句话说,从STDIN复制到一个变量是否在内存使用上是有效中立的?还是增加一倍的内存消耗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-08-03 00:25:33

你已经得到了一个很好的答案,但我对我的猜测并不满意,所以我决定测试我的假设。

我制作了一个简单的C++程序,名为streamstream,它只需要使用STDIN并以1024字节的块将其写入STDOUT。看起来是这样的:

代码语言:javascript
复制
#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运行它,同时将输出从一个连接到另一个,如下所示:

代码语言:javascript
复制
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。然后我再检查一下瓦朗的产量。

代码语言:javascript
复制
#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以上。

代码语言:javascript
复制
KB
 137.0^                                                                      :#
      |                                                                     ::#
      |                                                                   ::::#
      |                                                                  :@:::#
      |                                                                :::@:::#
      |                                                              :::::@:::#
      |                                                            :@:::::@:::#
      |                                                          :@:@:::::@:::#
      |                                                         ::@:@:::::@:::#
      |                                                       :@::@:@:::::@:::#
      |                                                     :@:@::@:@:::::@:::#
      |                                                   @::@:@::@:@:::::@:::#
      |                                                 ::@::@:@::@:@:::::@:::#
      |                                               :@::@::@:@::@:@:::::@:::#
      |                                              @:@::@::@:@::@:@:::::@:::#
      |                                            ::@:@::@::@:@::@:@:::::@:::#
      |                                          :@::@:@::@::@:@::@:@:::::@:::#
      |                                        @::@::@:@::@::@:@::@:@:::::@:::#
      |                                      ::@::@::@:@::@::@:@::@:@:::::@:::#
      |                                    ::::@::@::@:@::@::@:@::@:@:::::@:::#
    0 +----------------------------------------------------------------------->ki
      0                                                                   210.9

但问题是,由于这种方法,内存的总使用量是多少?我找不到一个很好的工具来测量一组交互进程的内存占用时间。ps在这里似乎不够精确,即使我插入了一堆睡眠。但是我们可以解决这个问题:128 at的缓冲区只有在程序执行结束时,在写入流之后才被释放。但是,在编写流时,程序的另一个实例构建了自己的128 is缓冲区。因此,我们知道我们的内存使用量将攀升到2x128 we。但是,通过链接更多的程序实例,它不会上升到3x或4x128 or,因为我们的实例释放了它们的内存,并且在完成对STDOUT的写入之后,它们就会关闭。

票数 2
EN

Stack Overflow用户

发布于 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,并退出自身。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45471910

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档