Memory 更糟糕的罪恶:副作用还是传递大量物体?

Memory 更糟糕的罪恶:副作用还是传递大量物体?,memory,r,function,global-variables,side-effects,Memory,R,Function,Global Variables,Side Effects,我在一个循环中有一个函数在一个函数中。内部函数在内存中获取并存储一个大的数据向量(作为一个全局变量…我使用的是“R”,类似于“S-Plus”)。循环遍历一长串要获取的数据。外部函数启动进程并传入要获取的数据集列表 for (dataset in list_of_datasets) { for (datachunk in dataset) { <process datachunk> <store result? as vector? where?>

我在一个循环中有一个函数在一个函数中。内部函数在内存中获取并存储一个大的数据向量(作为一个全局变量…我使用的是“R”,类似于“S-Plus”)。循环遍历一长串要获取的数据。外部函数启动进程并传入要获取的数据集列表

for (dataset in list_of_datasets) {
  for (datachunk in dataset) {
    <process datachunk>
    <store result? as vector? where?>
  }
}
for(数据集列表中的数据集){
for(数据集中的数据块){
}
}
我将内部函数编程为在移动到下一个数据集之前存储每个数据集,因此外部函数的所有工作都会对全局变量产生副作用。。。一个大禁忌。这比收集并返回一个巨大的、占用内存的向量更好还是更糟糕?有更好的第三种方法吗


如果我将数据向量存储在数据库而不是内存中,答案会改变吗?理想情况下,我希望能够终止函数(或使其因网络超时而失败),而不会丢失终止前处理的所有信息。

如果不知道所使用的语言/编译器,很难说清楚。但是,如果只需将指针/引用传递给正在创建的对象,那么对象本身的大小与函数调用的速度无关。处理这些数据可能是另一回事。

在外部函数中使用变量,而不是全局变量。这两种方法都是最好的:你没有改变全局状态,也没有复制大量数据。如果必须提前退出,只需返回部分结果


(请参阅R手册中的“范围”部分:)

第三种方法:内部函数返回对大数组的引用,循环中的下一条语句将其解引用并存储在需要的任何位置(理想情况下使用单指针存储,而不必复制整个数组)


这消除了副作用和大数据结构的传递。

这不会对内存使用产生太大影响,因此您最好将代码清理干净

由于R对变量具有copy-on-modify,因此修改全局对象将具有与在返回值中传递内容相同的内存含义

如果将输出存储在数据库(甚至文件)中,则不会出现内存使用问题,并且数据将在创建时逐渐可用,而不仅仅是在最后。数据库的速度是否更快主要取决于您使用了多少内存:垃圾收集的减少是否将支付写入磁盘的成本


R中既有时间分析器,也有内存分析器,因此您可以从经验上看到影响是什么。

我不确定我是否理解这个问题,但我有一些解决方案

  • 在函数内部,创建向量列表并返回该列表

  • 在函数内部,创建一个环境并存储其中的所有向量。只要确保在出现错误时返回环境即可

  • 在R中:

    帮助(环境)
    #您可以这样做:
    外部记住你的知识。“过早优化是所有编程邪恶的根源。”


    试试无副作用的版本。看看它是否符合你的绩效目标。如果有,很好,你一开始就没有问题;如果没有,则使用副作用,并为下一个程序员记下你的手是被迫的。

    供参考,以下是避免副作用的完整玩具解决方案示例:

    outerfunc <- function(names) {
      templist <- list()
      for (aname in names) {
        templist[[aname]] <- innerfunc(aname)
      }
      templist
    }
    
    innerfunc <- function(aname) {
      retval <- NULL
      if ("one" %in% aname) retval <- c(1)
      if ("two" %in% aname) retval <- c(1,2)
      if ("three" %in% aname) retval <- c(1,2,3)
      retval
    }
    
    names <- c("one","two","three")
    
    name_vals <- outerfunc(names)
    
    for (name in names) assign(name, name_vals[[name]])
    

    outerfunc我建议编辑这篇文章,加入一些简短的伪代码,以便更容易了解您想要做什么。是的,请添加伪代码,不可能知道您的意思。当你说“处理……并存储结果”时,你的意思是“存储完全相同的字符串”,还是向量(整数、引用词),还是什么?您是否将其作为记录存储在某个巨大的数据帧/数组/矩阵中?让我们了解一下行数、列数、文件、块和向量大小,以及您的工作内存?
    
    outerfunc <- function(names) {
      templist <- list()
      for (aname in names) {
        templist[[aname]] <- innerfunc(aname)
      }
      templist
    }
    
    innerfunc <- function(aname) {
      retval <- NULL
      if ("one" %in% aname) retval <- c(1)
      if ("two" %in% aname) retval <- c(1,2)
      if ("three" %in% aname) retval <- c(1,2,3)
      retval
    }
    
    names <- c("one","two","three")
    
    name_vals <- outerfunc(names)
    
    for (name in names) assign(name, name_vals[[name]])