编译时间与运行时间? [英] compile time vs. run time?

查看:96
本文介绍了编译时间与运行时间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含这样的代码的大类(代码是根据某些配置自动生成的
):


if(str == " name1"){

do;

something;

name1_specific;

} else if(str = =" name2"){

do;

something;

name2_specific;

} else ...


现在,因为我有数百个这样的name1,name2,...代码需要永远

来编译。更糟糕的是,如果配置中只有一个名称发生变化,那么

整个代码会重新生成,我必须等待很长时间的编译。


一些单独的编译是个好主意?


// main.cpp

if(str ==" name1"){

processName1();

}否则if(str ==" name2"){

processName2();

}否则......


// name1.cpp

void processName1(){...}


// name2.cpp

void processName2(){...}

// ...

现在,如果我必须修改name1.cpp,它不会再影响整个代码了,

和编译会很快。


但它是否影响运行时?这些processName1()...函数可以自动内联

吗?或者单独的编辑是否使这不可能?


谢谢!

Markus

解决方案

" Markus Dehmann" <毫安************ @ gmail.com>写道......

[...]
但是它会影响运行时吗?这些processName1()...函数可以自动内联吗?或者单独的编译是否使得这不可能?




如果编译器在生成代码时知道其

实体的内容,则只能内联函数用于调用该函数。如果没有机构可以看到,那么编译器会用什么代替电话呢?


V


< blockquote>Markus Dehmann <毫安************ @ gmail.com>在消息中写道

新闻:35 ************* @ individual.net ...

我有一个大的包含这样的代码的类(根据某些配置自动生成代码):

if(str ==" name1"){
do;
某事;
name1_specific;
} if if(str ==" name2"){
do;
某事;
name2_specific;
}否则...

现在,因为我有数百个这样的name1,name2,...代码需要
永远编译。更糟糕的是,如果配置中只有一个名称发生变化,那么整个代码会重新生成,我必须等待很长时间的编译。

一些单独的编译是否会很好理念?


是的。取决于正文if if块,非内联

函数调用甚至虚函数的成本通常可以忽略不计。 Meausre

首先是性能影响,必要时使用分析器,只有这样才能内联




// main .cpp
if(str ==" name1"){
processName1();
} else if(str ==" name2"){
processName2();
}否则......

// name1.cpp
void processName1(){...}
// name2.cpp
void processName2(){...}
// ...


他们不会在我知道的所有编译器中自动内联。

但是,您可以使用

#ifndef _DEBUG强制编译器在发布版本中执行此操作。例如,


// main.cpp

#ifdef _DEBUG

#include" name1.h"

#include" name2.h"

#else

#include" name1.inl"

#include" ; name2.inl"

#endif

int main(){

std :: string str;

if(str == tagName1){

processName1();

} else if(str == tagName1){

processName2();

}否则......

}


// maybeinline.h

#ifdef _DEBUG

#define maybeinline

#else

#define maybeinline inline

#endif

// name1.h

#ifndef processName1

#define processName1

extern const char * const tagName1;

void processName1();

#endif


// name1.inl

#include" name1 .h"

#include" maybeinline.h"

maybeinline void processName1(){...}

#endif


// name1.cpp

#include" name1.inl"

const char * const tagName1 =" name1";

更重要的是,请考虑使用命令模式。会有一个

asbtract类的BaseAction或者一些名字,带有一个纯虚函数exec或者

一些名字。函数exec通常会带一个或多个函数

参数。将有一个具有向量< BaseAction *>的注册表。或者

喜欢。人们将在单独的文件中定义派生的动作类。

注册表将提供一种向创建新派生的函数添加新派生动作或指针

的方法功能,到注册表。当

将一个新的派生操作添加到注册表时,还会添加

操作的名称(或者提供一个返回名称名称的虚函数

行动)。要运行给定函数名称的操作,请求注册表

返回BaseAction *,其函数名称等于您要运行的

函数的名称,然后调用虚拟exec函数。


现在当你向注册表中添加新函数时,你不必通过添加更多if-else来改变main.cpp
块,你也不必重新编译

吧。这有助于维护很多。


但它是否会影响运行时间?这些processName1()...函数可以自动内联
吗?或者单独的编译是否使得这不可能?




嗯,有一种方法可以进行内联,如上所示。但是我的经验中,

的成本通常(但并非总是)可忽略不计。

非内联虚拟函数调用。此外,如果每个函数 - processName1,processName2

等 - 是内联的,那么你的函数int main()将非常大。这可能通过引入分页来降低性能。我不知道有关

分页的详细信息,因为它是操作系统,CPU和RAM特定的,但它有事情要做

而无法将整个程序代码保存在一块内存中,因此编译器必须始终交换程序代码。


Markus,


通过使用

不同进程的查找表,可以使代码更简单。 (或者他们是什么)。

查找表数组的每个元素都将存储一个字符串和一个函数指针。然后,

您的代码可以迭代数组,并在字符串匹配时调用相应的

函数指针。


这更容易维护。它还可以加快编译速度,因为你可以将查询表放在与过程函数的

实现单独的文件中。

但是它会影响运行时吗?这些processName1()...函数可以自动内联
吗?或者单独的编译是否使得这不可能?




这真的是代码中的瓶颈吗?

记住Knuth所说的:过早优化是所有

邪恶的根源。


Joseph


I have a big class that contains code like this (the code is automatically
generated according to some configuration):

if(str == "name1"){
do;
something;
name1_specific;
}else if(str == "name2"){
do;
something;
name2_specific;
}else...

Now, since I have hundreds of these name1, name2, ... the code takes forever
to compile. Even worse, if only one name changes in the configuration, the
whole code gets re-generated and I have to wait on compilation very long.

Would some amount of separate compilation be a good idea?

// main.cpp
if(str == "name1"){
processName1();
}else if(str == "name2"){
processName2();
}else...

// name1.cpp
void processName1(){...}

// name2.cpp
void processName2(){...}

// ...
Now, if I have to modify name1.cpp, it won''t affect the whole code anymore,
and compilation will be quick.

But does it affect runtime? Can these processName1()... functions be inlined
automatically? Or does the separate compilation make that impossible?

Thanks!
Markus

解决方案

"Markus Dehmann" <ma************@gmail.com> wrote...

[...]
But does it affect runtime? Can these processName1()... functions be
inlined
automatically? Or does the separate compilation make that impossible?



Functions can only be inlined if the compiler knows the contents of their
bodies when generating code for a call to that function. If no body is
visible, what would the complier put instead of the call?

V


"Markus Dehmann" <ma************@gmail.com> wrote in message
news:35*************@individual.net...

I have a big class that contains code like this (the code is automatically
generated according to some configuration):

if(str == "name1"){
do;
something;
name1_specific;
}else if(str == "name2"){
do;
something;
name2_specific;
}else...

Now, since I have hundreds of these name1, name2, ... the code takes forever to compile. Even worse, if only one name changes in the configuration, the
whole code gets re-generated and I have to wait on compilation very long.

Would some amount of separate compilation be a good idea?
Yes. Depending on the body if the if blocks, the cost of a non-inline
function call or even a virtual function is generally negligible. Meausre
the performance impact first, using a profiler if necessary, and only then
should you inline.

// main.cpp
if(str == "name1"){
processName1();
}else if(str == "name2"){
processName2();
}else...

// name1.cpp
void processName1(){...}

// name2.cpp
void processName2(){...}

// ...
They won''t be inlined automatically in all the compilers I know of.
However, you can force the compiler do do this in the release build by using
#ifndef _DEBUG. For example,

// main.cpp
#ifdef _DEBUG
#include "name1.h"
#include "name2.h"
#else
#include "name1.inl"
#include "name2.inl"
#endif
int main() {
std::string str;
if(str == tagName1){
processName1();
}else if(str == tagName1){
processName2();
}else...
}

// maybeinline.h
#ifdef _DEBUG
#define maybeinline
#else
#define maybeinline inline
#endif

// name1.h
#ifndef processName1
#define processName1
extern const char *const tagName1;
void processName1();
#endif

// name1.inl
#include "name1.h"
#include "maybeinline.h"
maybeinline void processName1() { ... }
#endif

// name1.cpp
#include "name1.inl"
const char *const tagName1 = "name1";
More importantly, consider using the command pattern. There will be an
asbtract class BaseAction or some name, with a pure virtual function exec or
some name. The function exec will normally take one or more function
arguments. There will be a registry that has a vector<BaseAction*> or the
like. People will define their derived action classes in seperate files.
The registry will provide a way of adding a new derived action or a pointer
to a function that creates a new derived function, to the registry. When
one adds a new derived action to the registry, one also adds the name of the
action (or provides a virtual function that returns the name of the name of
the action). To run an action given a function name, ask the registry to
return the BaseAction* whose function name equals to the name of the
function you want to run, then call the virtual exec function.

Now when you add new functions to the registry, neither do you have to
change main.cpp by adding more if-else blocks, nor do you have to recompile
it. This helps maintainance a lot.

But does it affect runtime? Can these processName1()... functions be inlined automatically? Or does the separate compilation make that impossible?



Well, there is a way to get inlining, as indicated above. But the cost of a
non-inline virtual function call is usually (but not always) negligible in
my experience. Furthermore, if every function -- processName1, processName2
etc -- is inline, your function int main() will be very large. This could
degrade performance by introducing paging. I don''t know the details about
paging as it is OS and CPU and RAM specific, but it''s got something to do
with not being able to keep the entire program code in a single chunk of
RAM, so the compiler has to swap program code in and out all the time.


Markus,

You could make your code much simpler by having a lookup table of the
different "processes" (or whatever they are). Each element of the
lookup table array would store a string and a function pointer. Then,
your code could just iterate over the array, and call the appropriate
function pointer when there''s a string match.

This is much easier to maintain. It will also speed your compilation,
since you can have your lookup table in a separate file from the
implementation of the process functions.

But does it affect runtime? Can these processName1()... functions be inlined automatically? Or does the separate compilation make that impossible?



Is this really the bottleneck in your code?
Remember what Knuth said: Premature optimization is the root of all
evil.

Joseph


这篇关于编译时间与运行时间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆