Sign in to follow this  
Keba

DLL performance

Recommended Posts

Keba    170
I had heard that there is a performance penalty when i'm using dynamic linked libraries(DLL).... I'm designing a system(for a game) with a bounce of DLLS and I was wondering if a static libray is a better chooise? if the penalty of DLLs is going to affect the performance? hmm i know that you can't say something like: "3 dlls will drop your framerate with 40 fps"...but i wan't to know a little more about this / thanks

Share this post


Link to post
Share on other sites
SirLuthor    364
As far as I know, the only overhead that can possibly occur through use of DLLs is the following. Firstly, when you load it, overhead will be incurred due to the fact that Windows has to map it's code into the processes address space, and do some other stuff. Secondly, there will the overhead of having to call the DLL's exported functions through a function pointer instead of calling them directly. This is of course assuming that you are speaking of run-time linking, that is, loading your DLL manually through LoadLibrary(...). If you are using compile time, or static linking, then neither of those should be a problem.

Keep in mind that I may in fact be incorrect in some of the details [smile] Hope this helps!

Share this post


Link to post
Share on other sites
markr    1692
There is a startup penalty, but the runtime performance should not be different than using a statically linked library.

At least, if you discount things like inlining. The only way I can think using a DLL can make things slower is by preventing the compiler doing optimisations it might otherwise do.

Even if there is a performance hit, it should be pretty small - try profiling it yourself.

If your other reasons for using a DLL are valid, don't change because of some perceived tiny performance issue.

Mark

Share this post


Link to post
Share on other sites
Spoonbender    1258
Quote:
Original post by markr
There is a startup penalty, but the runtime performance should not be different than using a statically linked library.

Well, the functions still have to be called through function pointers, which does add a (small) performance overhead. At least, I can't see how it can be avoided. Then again, I don't know exactly how dll's are actually implemented, so they might have a dozen clever tricks up their sleeves... [wink]

Share this post


Link to post
Share on other sites
doynax    850
Quote:
Original post by Trap
Cost of DLLs:
At worst it is 1 additional pointer dereference per call.
No, it can also heavily affect your compiler's optimization ability if you cross DLL boundaries a lot.
Every time you call a (non-inlined) DLL function the compiler *has* to assume that anything can happen. Whereas with a static library modern compilers can inline across the boundaries, analyze aliasing constraints, apply profiler-guided optimizations, etc..
Additionally the DLL has to preserve all exported functions, and generally their full names too, which can make your application a lot larger.

Share this post


Link to post
Share on other sites
notamac    122
However, if your project begins to get large, then splitting things up into DLL's is going to dramatically improve your link time. This can be a nice productivy boost when dealing with moderate to large sized projects. Also, you'll usually expose things from DLL's as interfaces (or at least - you should!) and if you follow the good rule of only exporting a single symbol (the CreateMainInterface() function) from the DLL, it forces a lot of encapsulation, which is again a boon if you have more than one developer.

Share this post


Link to post
Share on other sites
chollida1    532
Quote:
Original post by notamac
However, if your project begins to get large, then splitting things up into DLL's is going to dramatically improve your link time. This can be a nice productivy boost when dealing with moderate to large sized projects. Also, you'll usually expose things from DLL's as interfaces (or at least - you should!) and if you follow the good rule of only exporting a single symbol (the CreateMainInterface() function) from the DLL, it forces a lot of encapsulation, which is again a boon if you have more than one developer.


Agreed with teh link time comment, but this speed up comes at the cost of startup time on your app. ie if you statically link your app will start faster as the loader doesn't need to load the dll into memory and then match up the exe's imports with the dll's exports.

Cheers
Chris

Share this post


Link to post
Share on other sites
doynax    850
Quote:
Original post by chollida1
Agreed with teh link time comment, but this speed up comes at the cost of startup time on your app. ie if you statically link your app will start faster as the loader doesn't need to load the dll into memory and then match up the exe's imports with the dll's exports.
True, but it's still a lot faster than the full linking procedure especially when optimizing at link time.
And instead of having to jump all over the place fixing up single calls, importing a DLL simply consits of fixing a few entries in a separate import table. So there's no need load the whole program.

Share this post


Link to post
Share on other sites
hplus0603    11356
On Windows, a DLL call actually vectors through a jump table, so there is one extra indirection in the call stream compared to static libraries (this is for hard-linked DLLs, i e you link with the .lib import library at link time).

On Linux, a DLL (.so) call can actually be patched up to go directly to the site, if the loader and linker co-operate to make it so. However, the Linux position-independent-code methodology is fairly cumbersome, and generates lots of poorly performing glue code, so you should attempt not to use -fPIC.

You'll get the best performance characteristic if you have just a few global functions in your DLL, and make those functions return pointers to an abstract base class (interface). Calls through that interface (virtual functions) will be the same efficiency between DLLs as within the application.

Share this post


Link to post
Share on other sites
cbenoi1    484
> I had heard that there is a performance penalty
> when i'm using dynamic linked libraries(DLL)....

There is no difference in performance whatsoever between EXE and DLL when it comes to running the actual code, that is once the code is loaded in memory. The performance difference comes at DLL loading time. Here are a few tips & tricks about using DLLs that can enhance performance.

a) You can delay-load a DLL until it is needed by the application. For example, by putting the victory dance code in a separate DLL, you can accelerate things by putting off use of that code for later (and only if the gamer wins). Check the delay-load linker switches for this feature.

b) Use the /BASE switch of the linker to specify where the DLL will land in memory at load-up. Why? Using the default linker settings, all your compiled DLLs will end up in the same address space. Smart Win32 OS will do an address fixup pass to move the DLL around to avoid collisions, which will create a new code copy instead of solely relying on the memorymap mechanism. So you end up memory-mapping your DLL, modify each and every 4K blocks, and swap it out again to disk... not efficient use of swapping.

c) Use explicit linkage (LoadLibrary()/GetProcAddress()) when possible. This allows your application to make a decision about specific code section. Your user has turned off the music completely: why load the music DLL then? The gamer plays solo: don't load the network code.

d) Coalesce related code segments into 4K blocks. Why? The memory-map unit has a 4K granularity (8K on MIPS architectures and I64 like Vista). By putting all your setup UI dialog box code in a single segment allows the OS to page this segment out when it's no longer needed and this segment's LRU will eventually get marked as recyclable by the OS. Check the 'code_seg' pragmas of the compiler. If you scatter the code segments all over the place, then you stand a chance of *maximizing* your app's memory footprint (not a smart thing) and thus increase its sensitivity to swap. By coalescing related code segments you are *minimizing* your memory footprint.

You can get more info about how EXE and DLLs are loaded into memory here

Hope this helps.

-cb

Share this post


Link to post
Share on other sites
SiCrane    11839
Quote:
Original post by cbenoi1
There is no difference in performance whatsoever between EXE and DLL when it comes to running the actual code, that is once the code is loaded in memory.

Not really true. The DLL loading mechanism means that every call to a function in a DLL is effectively through a funciton pointer, which is slightly slower than a standard function call, and also tends to have poorer cache consistency than standard function calls.

Share this post


Link to post
Share on other sites
cbenoi1    484
> Not really true.

It's a question of granularity. If you put a small piece of code in a DLL and call it within a tight loop, then yes, you will notice a small difference. Otherwise, with larger granularity calls the small overhead will be absorbed and become unnoticeable.

-cb

Share this post


Link to post
Share on other sites
SiCrane    11839
It doesn't even need to be a tight loops to cause performance decrease as the indirections create a definate cache impact, and the way that segments are allocated in modules means that it tends to create a disproportionate number of reads being done from the same set of cache lines. This can be very significant if you have a two or four way associative L1 cache. This actually becomes more significant if the DLL calls are not in a tight loop as it increases the size of the effective memory working set.

Either way it's still different from your claim of "no difference in performance whatsoever".

Share this post


Link to post
Share on other sites
iMalc    2466
Quote:
Original post by SiCrane
It doesn't even need to be a tight loops to cause performance decrease as the indirections create a definate cache impact, and the way that segments are allocated in modules means that it tends to create a disproportionate number of reads being done from the same set of cache lines. This can be very significant if you have a two or four way associative L1 cache. This actually becomes more significant if the DLL calls are not in a tight loop as it increases the size of the effective memory working set.

Either way it's still different from your claim of "no difference in performance whatsoever".
As much as I think there is probably some merrit in what you're saying, I really hope it wont needlessly push the OP into shoving his DLL code into a lib file or even the exe. I'm sure you don't want that either.

I very much doubt that the rest of his code is so efficient that a DLL boundary is the bottleneck. The OP has not profiled, he has merely heard rumours and some of you might be confirming his worst fears of those rumours. As always, get it working first, then if it's too slow, PROFILE, then optimise.[smile]

I think everyone posting in this thread should read hplus0603's post too.[cool]

Share this post


Link to post
Share on other sites
SiCrane    11839
I just get annoyed when people post things like "no difference in performance whatsoever" when there is a difference. As I said, it's slightly slower, not OMG IT'LL RUIN EVERYTHING slower.

Share this post


Link to post
Share on other sites
Aryabhatta    186
The people who say that having DLLs does not impact runtime performance are WRONG.

Some disadvantages using a DLL (apart from startup costs)

1) Compiler optimizations might not be as good compared to static linking.
2) Page Faults. This could increase and can be a big performance hit.
3) MultiThreading. If your app is multithreaded you can be affected by having many DLLS in your app. By default Windows calls the startup/shutdown routines for each DLL for every thread that is created/destroyed. Windows provides an API DisableThreadLibraryCalls to avoid calling these routines. (each DLL must call it)

That said, if used correctly (which is not hard), the advantage of using DLLs can outweigh the disadvantages.

Share this post


Link to post
Share on other sites
Keba    170
Ok, alot of answers...thank you all...
anyway, maybe i should specify my question a little bit...
how about this..

class API CSomeClass
{
public:
// some public functions

protected:
// some protected funcions/datamembers

};

where API is the classic

#ifdef PART_OF_DLL
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif


...as you can se i didn't export any interface, which means i want load this "dynamicly" with LoadLibrary...
instead the compiler creates the LIB files, which are included in the project which use the code and DLL are applied to the program so it can run with no errors.

Now...is this costly?
i Could load them with LoadLibrary, but these parts are used often and widely, so i don't see the reason why i should load them later. There are also many functions and classes in these DLL:s which also are called often. a exampel could be the render system.

Is it better to load these as static libraries?

Share this post


Link to post
Share on other sites
Basiror    241
when working with dlls should one use alloc functions passed from the main program? or are the dll and the programms addressspace merged per dll instance?

Share this post


Link to post
Share on other sites
S1CA    1418
Quote:
Original post by Basiror
when working with dlls should one use alloc functions passed from the main program? or are the dll and the programms addressspace merged per dll instance?


1) When you read a page from the DLL, the address is the location of the DLL image (though the address will be valid for your process); When you write to a page in the DLL (inside the DLL or inside the process that loaded), then that page is copied and mapped for the currently active process. This means that when you *write* to a global/static variable in a DLL, the value you write is only for the current process; it won't be shared across processes using that DLL (unless you specifically mark the pages as shared).


2) It's generally a safer practice (and cleaner from a design standpoint) to have destruction of a resource in the same place as the creation of that resource; so if some resource was created inside the DLL, ideally it should be destroyed inside the DLL.
Why is it safer? In the case of memory allocation (malloc, free, new & delete), it's *essential* that the version of the C runtime library used to allocate the memory is *identical* to the version used to free that memory.
If for example the application using your DLL uses the multithreaded debug version of the CRT and your DLL uses the single threaded release version of the CRT, you can expect very bad things when you pass a new'ed pointer from one to the delete in the other.

Share this post


Link to post
Share on other sites
hplus0603    11356
If you call into a virtual function that happens to be defined in a DLL, then there is NO DIFFERENCE compared to a virtual function that happens to be defined in the EXE. Now, calling a virtual function is a little bit more expensive than calling a non-virtual function, but if you're already using interfaces, pure abstract bases, and all that good stuff, then DLLs don't add any extra cost at runtime. (It's exactly the same cycles -- the caller doesn't know whether he'll end up in a DLL or an EXE)

Share this post


Link to post
Share on other sites
chollida1    532
Quote:
Original post by doynax
Quote:
Original post by chollida1
Agreed with teh link time comment, but this speed up comes at the cost of startup time on your app. ie if you statically link your app will start faster as the loader doesn't need to load the dll into memory and then match up the exe's imports with the dll's exports.
True, but it's still a lot faster than the full linking procedure especially when optimizing at link time.
And instead of having to jump all over the place fixing up single calls, importing a DLL simply consits of fixing a few entries in a separate import table. So there's no need load the whole program.


Perhaps this is true, that's debatable:). In my area of work we try to push the processing into offline work so that the runtime of the program will be faster.

At Corel when we split our code out into many dll's we noticed taht it loaded slower that statically linked libs. This was evident even with rebasing:)

Cheers
Chris

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this