On 09/30/14 03:01, Bernd Edlinger wrote:
Sigh. Yea, I guess if we're hitting the allocator insanely hard,
scrubbing memory might turn out to slow things down in a significant
way. Or it may simply be the case that we're using free'd memory in
some way and with the MALLOC_PERTURB changes we're in an infinite loop
in the dumping code or something similar.


Yeah, that is an interesting thing.
I debugged that, and it turns out, that this is just incredibly slow.
It seems to be in the macro expansion of this construct:

#define t16(x) x x x x x x x x x x x x x x x x
#define M (sizeof (t16(t16(t16(t16(t16(" ")))))) - 1)

libcpp is calling realloc 1.000.000 times for this, resizing
the memory by just one byte at a time. And the worst case of
realloc is O(n), so in the worst case realloc would have
to copy 1/2 * 1.000.000^2 bytes = 500 GB of memory.

With this little change in libcpp, the test suite passed, without any
further regressions:

--- libcpp/charset.c.jj    2014-08-19 07:34:31.000000000 +0200
+++ libcpp/charset.c    2014-09-30 10:45:26.676954120 +0200
@@ -537,6 +537,7 @@ convert_no_conversion (iconv_t cd ATTRIB
    if (to->len + flen> to->asize)
      {
        to->asize = to->len + flen;
+      to->asize *= 2;
        to->text = XRESIZEVEC (uchar, to->text, to->asize);
      }
    memcpy (to->text + to->len, from, flen);

I will prepare a patch for that later.
Thanks for digging into this. We usually try to throttle this growth a little. Something like this would be consistent with other cases in GCC:

to->asize += to->asize / 4;



Interestingly, if I define MALLOC_CHECK_=3 _and_ MALLOC_PERTURB_
this test passes, even without the above change,
but the test case
       gfortran.dg/realloc_on_assign_5.f03 fails in this configuration,
which is a known bug: PR 47674. However it passes when only MALLOC_PERTURB_
is defined.

Weird...
Yea, but that's par for the course when dealing with memory errors.

Jeff

Reply via email to