• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
fir

(mingw/winapi) growing exe size when linking to psapi

10 posts in this topic

My app is 25 kb size when stripping symbols (-s) in no it has 62kb

When im linking to psapi (-lpsapi and using one function from it, psapi is winapi lib for process info etc) it grows to 175 k and with stripping symbols 75 k

 

no using psapi   25k  62k

using paspi       75k 175k

 

why it grows so large (i am using only one function and my app grows from 25k to 75k i dislike it because i like tiny executables)

 

Is there a way to shrink it to 25 k again?

 

0

Share this post


Link to post
Share on other sites

Have you already tried dynamic/runtime linking. Is the API open source, so that you can stripe all the unnecessary code out of it ?

0

Share this post


Link to post
Share on other sites

Have you already tried dynamic/runtime linking. Is the API open source, so that you can stripe all the unnecessary code out of it ?

 

psapi is some winapi but you must link to libe explicity -lpsapi

(also you must include header (#include <psapi.h>) out of

the normal windows.h (but present and included like windows.h)

 

- I dont know the difference agains other winapi where you do not

link explicite, why I must use header and link it 

 

I not tried the dynamic linking it would probably work (could eventaullt try it) but now I just wonder why it grows so (including whole windows.h

not fats out my exe and this psapi makes +50k)

0

Share this post


Link to post
Share on other sites

Are you sure you are doing this correctly, your MinGW install is good, and your computer has no malware on it?

 

My complete psapi.dll alltogether only weights 9,216 bytes, so even assuming you linked the DLL's complete binary code into your executable somehow (which is not how it works!), this couldn't explain an extra 50kiB.

 

Linking with psapi.dll the proper way using the import lib (-lpsapi) makes exactly zero difference here (it's probably a few bytes extra, but due to PE/COFF section size alignment, the final executable is exactly the same size).

Edited by samoth
1

Share this post


Link to post
Share on other sites

Are you sure you are doing this correctly, your MinGW install is good, and your computer has no malware on it?

 

My complete psapi.dll alltogether only weights 9,216 bytes, so even assuming you linked the DLL's complete binary code into your executable somehow (which is not how it works!), this couldn't explain an extra 50kiB.

 

Linking with psapi.dll the proper way using the import lib (-lpsapi) makes exactly zero difference here (it's probably a few bytes extra, but due to PE/COFF section size alignment, the final executable is exactly the same size).

 

strange,

 

mingw should be ok, as to malware cannot be sure but never saw

a manifestation of it and everything seem to be ok

 

psapi here 23 040 bytes, I could try disasembly etc matbe try to see

whats going on but maybe im too unexperienced - and thus this question

0

Share this post


Link to post
Share on other sites

Increasing the total linked size by over twice the size of the added library is completely abnormal. I guess there must be some other source of code, such as

  • C++ template instantiations that you use to call the new functions
  • potentially large pieces of whatever libraries this "psapi" depends on

 

There are plenty of tools to list the content of an executable file: they should allow you to see which sections grow and which sections remain the same between the two versions of the program.

Edited by LorenzoGatti
1

Share this post


Link to post
Share on other sites

I've tried this again with a different MinGW build (TDM-4.8.1), and done binary compares.

 

Wiht or without -lpsapi (when not actually using any functions from psapi) makes exactly zero difference (executables are binary identical except for the linker's timestamp in the PE header, but that one is different for every two builds).

 

When actually using a function from the library (I tried EnumProcesses), a few dozen bytes are added to .text (no surprise), and the function's name is added to the back of the file (presumably import table), as well as the library's name. Alltogether, fewer than a hundred bytes are different.

The total size of the executable remains exactly the same (again, because of PE section sizes, there are merely some fewer zeroes at the end).

 

So... if your executable grows by 50kiB, something must be seriously amiss.

1

Share this post


Link to post
Share on other sites

I've tried this again with a different MinGW build (TDM-4.8.1), and done binary compares.

 

Wiht or without -lpsapi (when not actually using any functions from psapi) makes exactly zero difference (executables are binary identical except for the linker's timestamp in the PE header, but that one is different for every two builds).

 

When actually using a function from the library (I tried EnumProcesses), a few dozen bytes are added to .text (no surprise), and the function's name is added to the back of the file (presumably import table), as well as the library's name. Alltogether, fewer than a hundred bytes are different.

The total size of the executable remains exactly the same (again, because of PE section sizes, there are merely some fewer zeroes at the end).

 

So... if your executable grows by 50kiB, something must be seriously amiss.

 

dont know i can link the binary if somebody would like to disasembly it or something, I feel not ready to this..

 

https://www.dropbox.com/s/q5htqxrv94oocq9/psapigrow.zip

 

here are both versions , i comented my prototype game code so it is only green dot moved by mouse - app

0

Share this post


Link to post
Share on other sites

One is compiled with exception support, and the other without.

 

You can easily tell by the presence (or absence) of __unexpected_handler_sh and __terminate_handler_sh or strings such as "terminate called after unhandled exception".

1

Share this post


Link to post
Share on other sites

One is compiled with exception support, and the other without.

 

You can easily tell by the presence (or absence) of __unexpected_handler_sh and __terminate_handler_sh or strings such as "terminate called after unhandled exception".

 

I carefull add -fno-rtti -fno-exceptions to all i compile and link, so

linking to psapi forces mingw to enable exceptions (and ignore my commands)? Is there a way to remove it?

0

Share this post


Link to post
Share on other sites

Linking pasapi should not (that would be nonsensical, since it's a C API) and, on my machine, does not force MinGW to enable exceptions.

 

Though using exceptions in any form does, obviously. Are you positively sure that you do not have anything like throw or catch in your sources? This includes headers from any other libraries that you may be including (which maybe have some #ifdef that you accidentially triggered?).

 

While I obviously cannot tell you the exact reason of why and where and how exception handling got turned on without my divining crystal ball, I can only tell you what the symptoms are. One of the files you uploaded on pastebin does contain the names and strings of the standard exception handling code, and the other one does not.

 

If you have MSYS or GnuWin or something similar on your computer, you can run something like grep exception psapilinked.exe to see yourself (or "unexpected" or "handler"). Or just use a hex editor (I used WinMerge to compare them, but HxD would work fine, too).

0

Share this post


Link to post
Share on other sites

Linking pasapi should not (that would be nonsensical, since it's a C API) and, on my machine, does not force MinGW to enable exceptions.

 

Though using exceptions in any form does, obviously. Are you positively sure that you do not have anything like throw or catch in your sources? This includes headers from any other libraries that you may be including (which maybe have some #ifdef that you accidentially triggered?).

 

While I obviously cannot tell you the exact reason of why and where and how exception handling got turned on without my divining crystal ball, I can only tell you what the symptoms are. One of the files you uploaded on pastebin does contain the names and strings of the standard exception handling code, and the other one does not.

 

If you have MSYS or GnuWin or something similar on your computer, you can run something like grep exception psapilinked.exe to see yourself (or "unexpected" or "handler"). Or just use a hex editor (I used WinMerge to compare them, but HxD would work fine, too).

 

No all headers im using are windows.h (with lean and mean and extra lean) and some c standard lib thats all - and psapi.h here - maybe this 

causes the exceptions? nothing other, I carefully add teh options to strip symbols, no exceptions, no runtime - I am using pure c code 

but compile it in c++ mode, this is simple and pure winapi app

 

got no idea what causes this exceptions.. do they have runtime cost

involved (I would like to strip them out)

0

Share this post


Link to post
Share on other sites

Linking pasapi should not (that would be nonsensical, since it's a C API) and, on my machine, does not force MinGW to enable exceptions.

 

Though using exceptions in any form does, obviously. Are you positively sure that you do not have anything like throw or catch in your sources? This includes headers from any other libraries that you may be including (which maybe have some #ifdef that you accidentially triggered?).

 

While I obviously cannot tell you the exact reason of why and where and how exception handling got turned on without my divining crystal ball, I can only tell you what the symptoms are. One of the files you uploaded on pastebin does contain the names and strings of the standard exception handling code, and the other one does not.

 

If you have MSYS or GnuWin or something similar on your computer, you can run something like grep exception psapilinked.exe to see yourself (or "unexpected" or "handler"). Or just use a hex editor (I used WinMerge to compare them, but HxD would work fine, too).

 

I did some tests yet , my psapi code is like that

 


#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#include <windows.h>
 
#include <psapi.h>
 
#include "..\allmyheaders\allmyheaders.h"
 

long working_set_size = -1;
long paged_pool_size = -1;
long nonpaged_pool_size = -1;
 
static PROCESS_MEMORY_COUNTERS process_memory_counters;
 
long GetMemoryInfo()
{
 
    static HANDLE hProcess;
 
    static int initialised = 0;
    if(!initialised)
    {
    // return -1;
     static DWORD processID = GetCurrentProcessId();
    // return -2;
     hProcess = OpenProcess(  PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
 
     if (NULL == hProcess)  ERROR_EXIT("cant open process for get memory info");
 
     initialised = 1;
 
 
    }
 
 
    if(GetProcessMemoryInfo(hProcess, &process_memory_counters, sizeof(process_memory_counters)))
    {
      working_set_size    = process_memory_counters.WorkingSetSize;
      paged_pool_size     = process_memory_counters.QuotaPagedPoolUsage;
      nonpaged_pool_size  = process_memory_counters.QuotaNonPagedPoolUsage ;
    }
 
    if(0)
      CloseHandle( hProcess );
 
    return working_set_size;
}
 
it shows that when i uncomment return -2 here my app has 75k when i uncomment return -1 (disabling the execution of
 
     static DWORD processID = GetCurrentProcessId();
 
the app has 25k - is it possible, can it be explained?
 
(same with dynamic linking regardless of static or dynamic it seems
that it all depends on this "     static DWORD processID = GetCurrentProcessId();" line
Edited by fir
0

Share this post


Link to post
Share on other sites

These two are quite hefty antipatterns:

I am using pure c code but compile it in c++ mode, this is simple and pure winapi app
#include "..\allmyheaders\allmyheaders.h"

 

You should either write C or C++ and compile the language that you use, not something different. C++ is not "C with some additional stuff", it is a different language with similar, but different rules. There is nothing wrong with writing C code, but then you should also compile as C. If you compile C++, then you should write C++.

 

Including "allmyheaders.h" is something that generally works, but it makes compilation needlessly slow, and you maybe bring definitions into scope which you don't need (or which even interfere in a non-obvious manner). It will also cause some people to raise an eyebrow when they look at your code, and will cause others to yell at you.

 

One notable difference of whether you compile C or C++ is for example that C++ (at least C++11, but GCC since ca. version 4.6 also does that for C++03) mandates initialization of function-local static variables being thread-safe. I'm mentioning that since you use that feature (maybe without being aware).

 

You most probably should not worry about exceptions. Do they have a runtime cost? Well, it depends, generally everything has a runtime cost. A better question would be whether they have a cost that matters, or a cost that is not justified by the benefits.

Giving a meaningful answer about exceptions is also hard since it depends a lot on what compiler build you use. MinGW can use setjump/longjump, DW2, and SEH exceptions. Which ones you have is determined when the compiler is built (on a proper build, you can figure out by running gcc -v).

 

SJLJ exceptions do have a runtime overhead, but even these are very acceptable, and the usefulness of exceptions still outweights their runtime cost in my opinion. DW2 exceptions make your exectuable somewhat bigger, but do not have a runtime overhead unless or until you actually throw (when trowing, they're indeed slightly slower). SEH exceptions combine the best of two worlds, but are presently only implemented in 64-bit builds (patent issues).

 

Exceptions have traditionally been accused of killing performance, but at least on a desktop, that is definitively not the case (it might be on a console). Like most language features, exceptions can be used for good and for evil. If you use them in a reasonable manner, their overhead will be very low (close to zero), but they will be immensely useful and greatly improve your code quality.

If you abuse them, ... well, the opposite. smile.png

 

 

disabling GetCurrentProcessId() [...] can it be explained?

 

I can't explain that. Does not seem like this is possible.

0

Share this post


Link to post
Share on other sites

These two are quite hefty antipatterns:

 

I am using pure c code but compile it in c++ mode, this is simple and pure winapi app
#include "..\allmyheaders\allmyheaders.h"

 

You should either write C or C++ and compile the language that you use, not something different. C++ is not "C with some additional stuff", it is a different language with similar, but different rules. There is nothing wrong with writing C code, but then you should also compile as C. If you compile C++, then you should write C++.

 

Including "allmyheaders.h" is something that generally works, but it makes compilation needlessly slow, and you maybe bring definitions into scope which you don't need (or which even interfere in a non-obvious manner). It will also cause some people to raise an eyebrow when they look at your code, and will cause others to yell at you.

 

One notable difference of whether you compile C or C++ is for example that C++ (at least C++11, but GCC since ca. version 4.6 also does that for C++03) mandates initialization of function-local static variables being thread-safe. I'm mentioning that since you use that feature (maybe without being aware).

 

You most probably should not worry about exceptions. Do they have a runtime cost? Well, it depends, generally everything has a runtime cost. A better question would be whether they have a cost that matters, or a cost that is not justified by the benefits.

Giving a meaningful answer about exceptions is also hard since it depends a lot on what compiler build you use. MinGW can use setjump/longjump, DW2, and SEH exceptions. Which ones you have is determined when the compiler is built (on a proper build, you can figure out by running gcc -v).

 

SJLJ exceptions do have a runtime overhead, but even these are very acceptable, and the usefulness of exceptions still outweights their runtime cost in my opinion. DW2 exceptions make your exectuable somewhat bigger, but do not have a runtime overhead unless or until you actually throw (when trowing, they're indeed slightly slower). SEH exceptions combine the best of two worlds, but are presently only implemented in 64-bit builds (patent issues).

 

Exceptions have traditionally been accused of killing performance, but at least on a desktop, that is definitively not the case (it might be on a console). Like most language features, exceptions can be used for good and for evil. If you use them in a reasonable manner, their overhead will be very low (close to zero), but they will be immensely useful and greatly improve your code quality.

If you abuse them, ... well, the opposite. smile.png

 

 

disabling GetCurrentProcessId() [...] can it be explained?

 

I can't explain that. Does not seem like this is possible.

 this allmyheaders.h is only with my own headers, from different modules (added here for convenience, (not to inllude specyfic list each one for each include) some way of short, also this 'my' name suggest this is some playfield (this is experimantal home project and not large)- except mu ovn headers I am using onlu std c lib (like stdio.h math.h stdlib.h) and windows.h

 

well my tests showed what i said if i wil uncomment return it is 75 k

if i give return vefore thi it is 25k

 

 

as to c /c++

 

I am big fan of c and not use c++ features, but i cant stand one thing

 

 

const int tab_max = 1000; //at global/file scope

int tab[tab_max];

 

it wil not compile in c - so i just need to switch to c++ simply for this 

one 'feature' (the only one i use)

0

Share this post


Link to post
Share on other sites

 

One notable difference of whether you compile C or C++ is for example that C++ (at least C++11, but GCC since ca. version 4.6 also does that for C++03) mandates initialization of function-local static variables being thread-safe. I'm mentioning that since you use that feature (maybe without being aware).

 

 

BINGO, (what a shit is this ;c )

 

I just turned 

static DWORD processID =  GetCurrentProcessId();

into

 

static DWORD processID = 0;
 processID = GetCurrentProcessId();
 
and the size dropped down from 75k to 27k
also spped of the ap from 4ms/frame dropped to 3ms/frame
 
so it seem there was some overgead or something
 
scary, important lesson learned - avoid such kind of static 'initialisations' (scarry , realy scary, i very much dislike when compiler do thi kind of staf degrading performance)
Edited by fir
0

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  
Followers 0