Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

static guard locks

42 views
Skip to first unread message

Prroffessorr Fir Kenobi

unread,
Aug 27, 2015, 2:12:43 PM8/27/15
to
Im not sure if this is a problem of c++
only or it appleies to c, too

Sometimes (usually?) when using static entities
in functions the compiler puts special code which
contains a lock acquire and release

Thisd bloats the executable yet also slows down the code.. Im not quite sure
1)how serious this problem is?
2) in which cases it do apply?
3) how to avoid it in most easy way?
4) how to be sure my app do not contains such sh*t?

Paavo Helde

unread,
Aug 27, 2015, 2:22:45 PM8/27/15
to
Prroffessorr Fir Kenobi <profes...@gmail.com> wrote in
news:e7402373-b475-48bf...@googlegroups.com:
This is required by C++11 for ensuring thread-safe creation of statics in
multithreaded applications. Your compiler probably has some switch or
pragma to turn this feature off. For gcc I was able to find this option via
google in ca 5 seconds.

Cheers
Paavo

Prroffessorr Fir Kenobi

unread,
Aug 27, 2015, 3:00:13 PM8/27/15
to
so how to turn it off ? i dont know the appriopriate naming to immediately find it

Prroffessorr Fir Kenobi

unread,
Aug 27, 2015, 3:06:18 PM8/27/15
to
besides that..isnt it silly (worse than silly) for gcc to do that - it slows and bloats code that do not need that...

does maybe someone know if it also applies to c?

Nobody

unread,
Aug 27, 2015, 3:09:03 PM8/27/15
to
On Thu, 27 Aug 2015 11:12:28 -0700, Prroffessorr Fir Kenobi wrote:

> Im not sure if this is a problem of c++ only or it appleies to c, too
>
> Sometimes (usually?) when using static entities in functions the compiler
> puts special code which contains a lock acquire and release
>
> Thisd bloats the executable yet also slows down the code.. Im not quite
> sure
> 1) how serious this problem is?

How frequently are those functions called? And if they're called from
multiple threads, how much contention do you expect for the locks?

If you don't need the functions to be re-entrant (i.e. you're not using
threads or such functions are never called from more than one thread),
with g++ you can use -fno-threadsafe-statics to remove the locks.

> 2) in which cases it do apply?

It occurs whenever you have a static local variable whose constructor
requires the execution of code (i.e. the compiler can't just store the
initial value in the data/bss segment, but must calculate it at run time),
and the compiler can't somehow optimise the locks away.

> 3) how to avoid it in most easy way?
> 4) how to be sure my app do not contains such sh*t?

Don't use static local variables. Put the variables at file scope so that
they're guaranteed to be initialised before main() is entered.

If you can't do that (e.g. because the initial value depends upon data
which hasn't been initialised at that point), then the construction has to
occur on the first call to the function, and the compiler has to allow for
the possibility that multiple threads call the function concurrently
(unless it has been told that this cannot happen; it's not as if it can
deduce that by itself).

Prroffessorr Fir Kenobi

unread,
Aug 27, 2015, 3:25:15 PM8/27/15
to
W dniu czwartek, 27 sierpnia 2015 21:09:03 UTC+2 użytkownik Nobody napisał:
> On Thu, 27 Aug 2015 11:12:28 -0700, Prroffessorr Fir Kenobi wrote:
>
> > Im not sure if this is a problem of c++ only or it appleies to c, too
> >
> > Sometimes (usually?) when using static entities in functions the compiler
> > puts special code which contains a lock acquire and release
> >
> > Thisd bloats the executable yet also slows down the code.. Im not quite
> > sure
> > 1) how serious this problem is?
>
> How frequently are those functions called? And if they're called from
> multiple threads, how much contention do you expect for the locks?
>

hell i dont know i got hundreds of them

though mostly they are simple statics
foo()
{
static int x = 1;
}
like that

are you sure this situation above do not generate such locks?

i used this swich and my app binary bloat went down 100KB from 350KB down to 250 KB *

what dam could generate whole 100kB of bloat?

im not using multithreaded only one core though sse optimised

* this was a half of a problem described in another thread near here, there is yet second
when changing compiler from gcc 4.6/4.7 to 4.8/4.9/5.1 frame time drops down from 20 ms to 23.5 ms - this switch elimineted bloat but has no effect on code slowdown

Paavo Helde

unread,
Aug 27, 2015, 4:37:03 PM8/27/15
to
Prroffessorr Fir Kenobi <profes...@gmail.com> wrote in
news:fb6a6b39-501e-4e84...@googlegroups.com:
I see Nobody has already provided the answer. FWIW, my google search
terms were: gcc avoid static mutex locks

>
> besides that..isnt it silly (worse than silly) for gcc to do that - it
> slows and bloats code that do not need that...

It's required by the C++11 standard. Most performance-critical C++ apps
are multithreaded nowadays in order to make use of multiple CPU cores, so
this makes a lot of sense. (And if your code is not performance-critical
you will not notice the difference).

Cheers
Paavo


Prroffessorr Fir Kenobi

unread,
Aug 27, 2015, 5:08:47 PM8/27/15
to
this above is probably untrue.. for example when i was writing my own multicore apps
i was using arrays of statics indexed by thread ordinal number (like 1,2,3,4)... that should probably work with no locks - im not sure as
i was not working/thinking longer on this

and here with this guard lock.. do this lock is acquired on every entry to the function or only once...? (i dont quite understand how it works)

beslides slowdown, bloat is scarry

Paavo Helde

unread,
Aug 27, 2015, 5:33:42 PM8/27/15
to
Prroffessorr Fir Kenobi <profes...@gmail.com> wrote in
news:8c23f29c-2663-445e...@googlegroups.com:
This sounds like thread-specific statics, there is a special keyword for
them in C++11 (thread_local).

>
> and here with this guard lock.. do this lock is acquired on every
> entry to the function or only once...? (i dont quite understand how it
> works)

What is protected is the initialization of the static. I guess depending
on the implementation this may or may not mean a mutex lock on each
entry.

>
> beslides slowdown, bloat is scarry

So care to provide numbers for the slowdown? How many percents your
program rans faster when compiled with -fno-threadsafe-statics?

About bloat: you must be using lots of statics. Time to start getting rid
of them, statics are evil even if multithreading is not involved.

Cheers
Paavo

Prroffessorr Fir Kenobi

unread,
Aug 28, 2015, 3:02:37 AM8/28/15
to
i checked some article


https://monoinfinito.wordpress.com/2013/12/03/static-initialization-in-c/

and here in the asm example there is showed that some bool check is done if this is already initialized

this probably means that it is called only once with entry when static is not yet initialised

(probably, as i still dont fully understand it, do some things like

struct X {int x; int y; int z; int w;};

foo()
{
static X x = {1,2,3,4};

}

initialized at compile time or on first entry point to function thus
guarded too?


> >
> > beslides slowdown, bloat is scarry
>
> So care to provide numbers for the slowdown? How many percents your
> program rans faster when compiled with -fno-threadsafe-statics?
>
> About bloat: you must be using lots of statics. Time to start getting rid
> of them, statics are evil even if multithreading is not involved.
>

i got many ststics but the simple ones, not sure but they probably do
not make guards and probably few that make querds - i think the 100KB bloat comes form another reason than
"50 bytes of so" x "number of guards"

Nobody

unread,
Aug 28, 2015, 8:22:06 PM8/28/15
to
On Thu, 27 Aug 2015 12:24:59 -0700, Prroffessorr Fir Kenobi wrote:

> though mostly they are simple statics foo()
> {
> static int x = 1;
> }
> like that
>
> are you sure this situation above do not generate such locks?

What code would be guarded by the lock in such a case?

Locks are only needed when the compiler has to generate code for the
initialisation (i.e. a constructor).

They shouldn't be needed for primitive types initialised from a constant,
or for plain "struct" types where the constructor just stores arguments in
fields (where the arguments are constants). In those cases, the compiler
can just store the variable's initial value in the data segment.

But if the compiler has to generate code to initialise the object (e.g.
because the value depends upon program state), it has to ensure that code
is only executed once even if two threads call the function concurrently.

> i used this swich and my app binary bloat went down 100KB from 350KB down
> to 250 KB *
>
> what dam could generate whole 100kB of bloat?

Linking in a library which wouldn't otherwise be required? Hard to say
without more detail.

Prroffessorr Fir Kenobi

unread,
Aug 29, 2015, 4:12:39 AM8/29/15
to
W dniu sobota, 29 sierpnia 2015 02:22:06 UTC+2 użytkownik Nobody napisał:
> On Thu, 27 Aug 2015 12:24:59 -0700, Prroffessorr Fir Kenobi wrote:
>
> > though mostly they are simple statics foo()
> > {
> > static int x = 1;
> > }
> > like that
> >
> > are you sure this situation above do not generate such locks?
>
> What code would be guarded by the lock in such a case?
>
> Locks are only needed when the compiler has to generate code for the
> initialisation (i.e. a constructor).
>
> They shouldn't be needed for primitive types initialised from a constant,
> or for plain "struct" types where the constructor just stores arguments in
> fields (where the arguments are constants). In those cases, the compiler
> can just store the variable's initial value in the data segment.
>

I thought so but asking to be a bit more sure (as sometimes weird things can go in play)

This code of my dont slows noticably as i got this guard quite outa loop
(its function is called 100 times per second only)(*) I also think that as its work out by this first initialization some bool or int flag
that is later only for read this flag then not need to be quarded (as all threads only read that), so this lock is only called once..

(*) but i also remember that i had such issue already about year ago
(it was putted n my psapi related code for asking system for consumed ram info - and there iirc it was also bloat and there noticable slowdown,
dont remember why as it was also only called 100fps only)

> But if the compiler has to generate code to initialise the object (e.g.
> because the value depends upon program state), it has to ensure that code
> is only executed once even if two threads call the function concurrently.
>
> > i used this swich and my app binary bloat went down 100KB from 350KB down
> > to 250 KB *
> >
> > what dam could generate whole 100kB of bloat?
>
> Linking in a library which wouldn't otherwise be required? Hard to say
> without more detail.

hard to provide more details here..
what could i do copmare two exe smaller and biger by some binary diff? disasemble and compare for differences?

David Brown

unread,
Aug 29, 2015, 6:34:52 AM8/29/15
to
Generate map files and compare them. You should be able to see a list
of the libraries that are linked in, and the sizes they take in the
executable.

Nobody

unread,
Aug 29, 2015, 7:53:43 PM8/29/15
to
On Sat, 29 Aug 2015 01:12:18 -0700, Prroffessorr Fir Kenobi wrote:

> what could i do copmare two exe smaller and biger by some binary diff?
> disasemble and compare for differences?

"objdump -h ..." will show the sizes of the individual sections.

0 new messages