我有大量数据要分析,我在编写代码时倾向于在单词或变量名之间留出空格,所以问题是,如果效率是第一要务,空白是否有成本?
c<-a+b 比 c <- a + b 更有效吗
对于第一,第二,第三,......,近似值,不,它根本不会花费你任何时间。
您花在按空格键上的额外时间比运行时的成本高出几个数量级(而且根本不重要)。
更大的成本将来自任何因遗漏空格而导致的可读性下降,这会使代码(对于人类)更难解析。
一句话,不!
library(microbenchmark)
f1 <- function(x){
j <- rnorm( x , mean = 0 , sd = 1 ) ;
k <- j * 2 ;
return( k )
}
f2 <- function(x){j<-rnorm(x,mean=0,sd=1);k<-j*2;return(k)}
microbenchmark( f1(1e3) , f2(1e3) , times= 1e3 )
Unit: microseconds
expr min lq median uq max neval
f1(1000) 110.763 112.8430 113.554 114.319 677.996 1000
f2(1000) 110.386 112.6755 113.416 114.151 5717.811 1000
#Even more runs and longer sampling
microbenchmark( f1(1e4) , f2(1e4) , times= 1e4 )
Unit: milliseconds
expr min lq median uq max neval
f1(10000) 1.060010 1.074880 1.079174 1.083414 66.791782 10000
f2(10000) 1.058773 1.074186 1.078485 1.082866 7.491616 10000
使用 microbenchmark 似乎是不公平的,因为表达式在循环中运行之前就已被解析。但是,使用source
应该意味着每次迭代都必须解析源代码并删除空格。所以我将函数保存到两个单独的文件中,文件的最后一行是函数的调用,例如我的文件 f2.R 如下所示:
f2 <- function(x){j<-rnorm(x,mean=0,sd=1);k<-j*2;return(k)};f2(1e3)
我像这样测试它们:
microbenchmark( eval(source("~/Desktop/f2.R")) , eval(source("~/Desktop/f1.R")) , times = 1e3)
Unit: microseconds
expr min lq median uq max neval
eval(source("~/Desktop/f2.R")) 649.786 658.6225 663.6485 671.772 7025.662 1000
eval(source("~/Desktop/f1.R")) 687.023 697.2890 702.2315 710.111 19014.116 1000
以及 1e4 复制的差异的视觉表示......
也许它确实在重复解析函数的情况下产生了微小的差异,但在正常用例中不会发生这种情况。
TL;DR 仅运行脚本以删除空格可能比通过删除空格节省的时间要长。
@Josh O'Brien 真的一针见血。但我无法抗拒基准
如您所见,如果您正在处理数量级为 1 亿条线,那么您将看到一个微小的阻碍。
然而 ,有了这么多行,它们很有可能成为至少一个(如果不是数百个)热点,其中简单地改进其中一个中的代码会给您带来比grep
消除所有空白更快的速度。
library(microbenchmark)
microbenchmark(LottaSpace = eval(LottaSpace), NoSpace = eval(NoSpace), NormalSpace = eval(NormalSpace), times=10e7)
@ 100 times; Unit: microseconds
expr min lq median uq max
1 LottaSpace 7.526 7.9185 8.1065 8.4655 54.850
2 NormalSpace 7.504 7.9115 8.1465 8.5540 28.409
3 NoSpace 7.544 7.8645 8.0565 8.3270 12.241
@ 10,000 times; Unit: microseconds
expr min lq median uq max
1 LottaSpace 7.284 7.943 8.094 8.294 47888.24
2 NormalSpace 7.182 7.925 8.078 8.276 46318.20
3 NoSpace 7.246 7.921 8.073 8.271 48687.72
在哪里:
LottaSpace <- quote({
a <- 3
b <- 4
c <- 5
for (i in 1:7)
i + i
})
NoSpace <- quote({
a<-3
b<-4
c<-5
for(i in 1:7)
i+i
})
NormalSpace <- quote({
a <- 3
b <- 4
c <- 5
for (i in 1:7)
i + i
})
这可能影响的唯一部分是将源代码解析为令牌。我无法想象解析时间的差异会很大。compile
但是,您可以通过使用包的或cmpfun
函数编译函数来消除此方面compiler
。然后解析只进行一次,任何空格差异都不会影响执行时间。
性能应该没有差异,尽管:
fn1<-function(a,b) c<-a+b
fn2<-function(a,b) c <- a + b
library(rbenchmark)
> benchmark(fn1(1,2),fn2(1,2),replications=10000000)
test replications elapsed relative user.self sys.self user.child
1 fn1(1, 2) 10000000 53.87 1.212 53.4 0.37 NA
2 fn2(1, 2) 10000000 44.46 1.000 44.3 0.14 NA
与microbenchmark
:
Unit: nanoseconds
expr min lq median uq max neval
fn1(1, 2) 0 467 467 468 90397803 1e+07
fn2(1, 2) 0 467 467 468 85995868 1e+07
所以第一个结果是假的..