Re: stdc++ issue: extremely long compile time with large number of string literals

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 10 Jul 2020 at 20:36, Mandeep Sandhu
<mandeepsandhu.chd@xxxxxxxxx> wrote:
>
> > Please reply to the mailing list, not just to me.
>
> Sorry, this must've happened by mistake (I almost always to a
> Reply-all when replying to messages from mailing lists)
>
> > >
> > > Thanks for the explanation. Still surprising that the performance
> > > degraded so much! Will this destruction loop run in quadratic time?
> >
> > No, only the compilation time is quadratic. The runtime performance
> > should be linear in the number of elements.
>
> Right, my question was poorly worded. When I said "Will this
> destruction loop run in quadratic time", I meant the time the compiler
> takes to create the exception handling code for N-1 elements.
>
> > I don't think you mean "raw string literals", do you?
> > "Raw string" has a very specific meaning:
> > https://en.cppreference.com/w/cpp/language/string_literal
>
> You're right, no I did not mean the one mentioned above (with the R
> prefix). Whats the correct term for a const char* (which is what I
> meant)?

Just a string literal. A raw string literal is the special kind with
the R prefix.

> >
> > Your email subject says "large number of string literals" but what
> > your code actually does is create a large
> > std::initializer_list<std::string>, which is not the same.
> >
> > If you do create string literals and then construct from that it
> > compiles much faster. This is similar to your original:
>
> Just to be sure I follow you, the following invokes
> std::initializer_list<std::string>
> std::unordered_set<std::string> s ({"a", "b", ...}); // this is what I
> reported the issue with
>
> but this does not?
> std::unordered_set<std::string> s {"a", "b", ...}; (and is faster?)

They're the same.

> >
> > $ printf '#include <unordered_set>\n#include
> > <string>\nstd::unordered_set<std::string> s{\n' > init.C ; seq
> > --format='"%.0f",' 1 50000 >> init.C ; printf '};\n' >> init.C
> > $ time g++ init.C -c
> >
> > real    1m57.054s
> > user    1m55.370s
> > sys     0m1.117s
>
> On my machine, this too compiles forever (its been compiling for 20+
> mins. I'm running on macbook with quad-core i7 & 8GB RAM)

Yes, that's the slow version.

> >
> > This creates an array of string literals and then constructs from that:
> >
> > $ printf '#include <unordered_set>\n#include
> > <string>\nstd::unordered_set<std::string> make_set() {\nconst char*
> > arr[] = {\n' > init2.C ; seq --format='"%.0f",' 1 50000 >> init2.C ;
> > printf '};\nreturn std::unordered_set<std::string>{std::begin(arr),
> > std::end(arr)};\n}\nauto s = make_set();\n' >> init2.C
> > tmp$ time g++ init2.C -c
> >
> > real    0m0.662s
> > user    0m0.591s
> > sys     0m0.069s
> >
> > As you can see, this is almost instant.
>
> Indeed it is! Although I have no idea why. Won't this form also
> require the same kind of exception handling code? when its iterating
> "arr", won't the compiler have to still ensure that prior objects are
> deleted if constructing a string obj from the current element fails?
>
> Or maybe the slowness comes from the way initializer_list specifically
> handles this?

It's the array of std::string that the std::initializer_list refers to
that causes the problem.

In the faster code there is no array of std::string, it's an array of
const char*. Initializing a const char* can't throw an exception, and
destroying it is a no-op, so there's no exception handling code needed
for the array.



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux