On Fri, 9 Jun 2023 at 17:20, Hans-Peter Nilsson <h...@axis.com> wrote:
> Hi! > > The test 27_io/basic_istream/ignore/wchar_t/94749.cc takes > about 10 minutes to run for cris-elf in the "gdb simulator" > here on my arguably way-past-retirement machine (and it > looks like it gained a minute with LRA). I've seen it > timing out every now and then on busy days with load > > `nproc`. Usually it happens some time after I've forgot > about why. :) > > It has had some performance surgery before (pruning for > simulators, doubling timeout for ilp32). I'd probably just > try cutting along the function boundaries and keep those > parts separate that have >1 min execution time. > test01, test02, test03 and test04 should run almost instantly. On my system they take about 5 microseconds each. So I don't think splitting those up will help. test05 extracts INT_MAX characters from a stream, which is a LOT of work. It doesn't actually read those from a file, the "stream" is a custom streambuf that contains a buffer of millions of wchar_t and "reading" from the stream just increments a counter into that buffer. But we do have to allocate memory for that buffer and then zero-init that buffer. That's a lot of cycles. Then once we've done that, we need to keep looping until we overflow a 32-bit counter (we don't increment by 1 every loop, so it overflows pretty quickly). Then we do it again and again and again! Each time takes about half a second for me. I thought it would help to avoid re-allocating the buffer and zeroing it again. If we reuse the same buffer, then we just have to loop until we overflow the 32-bit counter. That would make the whole test run much faster, which would reduce the total time for a testsuite run. Splitting the file up into smaller files would not decrease the total time, only decrease the time for that single test so it doesn't time out. I've attached a patch that does that. I makes very little difference for me, probably because allocating zero-filled pages isn't actually expensive on linux. Maybe it will make a differene for your simulator though? You could also try reducing the size of the buffer: +#ifdef SIMULATOR_TEST + static const streamsize bufsz = 16 << limits::digits10; +#else static const streamsize bufsz = 2048 << limits::digits10; +#endif test06 is the really slow part, that takes 10+ seconds for me. But that entire function should already be skipped for simulators. We can probably skip test05 for simulators too, none of the code it tests is platform-specific, so as long as it's being tested on x86 we don't really need to test it on cris-elf too.
diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/94749.cc b/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/94749.cc index 65e0a326c10..040e94aa4d6 100644 --- a/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/94749.cc +++ b/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/94749.cc @@ -89,7 +89,7 @@ struct buff : std::basic_streambuf<typename T::char_type, T> typedef std::streamsize streamsize; typedef std::numeric_limits<streamsize> limits; - buff() : count(0), buf() { } + buff() : count(0), nonzero_chars(), buf() { } int_type underflow() { @@ -112,12 +112,23 @@ struct buff : std::basic_streambuf<typename T::char_type, T> buf[headroom+1] = L'3'; this->setg(buf, buf, buf + headroom + 2); count = limits::max(); + nonzero_chars = headroom - 1; } return buf[0]; } + void reset() + { + buf[nonzero_chars] = char_type(); + buf[nonzero_chars+1] = char_type(); + buf[nonzero_chars+2] = char_type(); + nonzero_chars = 0; + count = 0; + } + streamsize count; + streamsize nonzero_chars; static const streamsize bufsz = 2048 << limits::digits10; char_type buf[bufsz + 2]; @@ -132,7 +143,8 @@ test05() typedef std::char_traits<C> T; - std::basic_istream<C, T> in(new buff<T>); + buff<T>* pbuf = new buff<T>; + std::basic_istream<C, T> in(pbuf); in.ignore(std::numeric_limits<std::streamsize>::max(), L'1'); VERIFY(in.good()); @@ -141,7 +153,9 @@ test05() VERIFY(in.get() == L'3'); VERIFY(in.get() == T::eof()); - delete in.rdbuf(new buff<T>); + pbuf->reset(); + in.clear(); + VERIFY(in.gcount() == 0); in.ignore(std::numeric_limits<std::streamsize>::max(), L'2'); VERIFY(in.good()); @@ -150,7 +164,9 @@ test05() VERIFY(in.get() == L'3'); VERIFY(in.get() == T::eof()); - delete in.rdbuf(new buff<T>); + pbuf->reset(); + in.clear(); + VERIFY(in.gcount() == 0); in.ignore(std::numeric_limits<std::streamsize>::max(), L'3'); VERIFY(in.good()); @@ -158,7 +174,9 @@ test05() VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max()); VERIFY(in.get() == T::eof()); - delete in.rdbuf(new buff<T>); + pbuf->reset(); + in.clear(); + VERIFY(in.gcount() == 0); in.ignore(std::numeric_limits<std::streamsize>::max(), L'4'); VERIFY(in.eof()); @@ -166,7 +184,8 @@ test05() VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max()); VERIFY(in.get() == T::eof()); - delete in.rdbuf(0); + in.rdbuf(0); + delete pbuf; } void @@ -177,7 +196,8 @@ test06() typedef __gnu_cxx::char_traits<C> T; - std::basic_istream<C, T> in(new buff<T>); + buff<T>* pbuf = new buff<T>; + std::basic_istream<C, T> in(pbuf); in.ignore(std::numeric_limits<std::streamsize>::max(), L'1'); VERIFY(in.good()); @@ -186,7 +206,9 @@ test06() VERIFY(in.get() == L'3'); VERIFY(in.get() == T::eof()); - delete in.rdbuf(new buff<T>); + pbuf->reset(); + in.clear(); + VERIFY(in.gcount() == 0); in.ignore(std::numeric_limits<std::streamsize>::max(), L'2'); VERIFY(in.good()); @@ -195,7 +217,9 @@ test06() VERIFY(in.get() == L'3'); VERIFY(in.get() == T::eof()); - delete in.rdbuf(new buff<T>); + pbuf->reset(); + in.clear(); + VERIFY(in.gcount() == 0); in.ignore(std::numeric_limits<std::streamsize>::max(), L'3'); VERIFY(in.good()); @@ -203,7 +227,9 @@ test06() VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max()); VERIFY(in.get() == T::eof()); - delete in.rdbuf(new buff<T>); + pbuf->reset(); + in.clear(); + VERIFY(in.gcount() == 0); in.ignore(std::numeric_limits<std::streamsize>::max(), L'4'); VERIFY(in.eof()); @@ -211,7 +237,8 @@ test06() VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max()); VERIFY(in.get() == T::eof()); - delete in.rdbuf(0); + in.rdbuf(0); + delete pbuf; } int