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.