in reply to xs outputs faster than perl can keep up

As diotalevi said, I suspect this is another variant of "suffering from buffering", i.e. the XS code is using a different output buffer than the Perl code.

I think some change will have to be made to the XS code: for example, (a) make it output the newlines itself (directly where it outputs the numbers), (b) make it use the same buffer that Perl's print or syswrite is using, (c) make sure the ouput from within XS is flushed every time after writing a number (this might still be tricky, though), or (d) change the API of Rmpfr_out_str() to return the number, so you can ouput everything synchronously from the Perl side... (I haven't looked at Math::MPFR - maybe there already is such a function...).

(a) or (d) is probably easiest, with (a) being fastest...

Replies are listed 'Best First'.
Re^2: xs outputs faster than perl can keep up
by syphilis (Archbishop) on Feb 07, 2007 at 05:44 UTC
    I think some change will have to be made to the XS code: for example, (a) make it output the newlines itself (directly where it outputs the numbers)

    That does fix the problem - ie in MPFR.xs replace
    SV * Rmpfr_out_str(SV * p, SV * base, SV * dig, SV * round) { if(SvIV(base) < 2 || SvIV(base) > 36) croak("2nd argument supplie +d to Rmpfr_out_str is out of allowable range (must be between 2 and 3 +6 inclusive)"); return newSVuv(mpfr_out_str(NULL, SvUV(base), SvUV(dig), *(INT2PT +R(mpfr_t *, SvIV(SvRV(p)))), SvUV(round))); }
    with
    SV * Rmpfr_out_str(SV * p, SV * base, SV * dig, SV * round) { unsigned long ret; if(SvIV(base) < 2 || SvIV(base) > 36) croak("2nd argument supplie +d to Rmpfr_out_str is out of allowable range (must be between 2 and 3 +6 inclusive)"); ret = mpfr_out_str(NULL, SvUV(base), SvUV(dig), *(INT2PTR(mpfr_t +*, SvIV(SvRV(p)))), SvUV(round)); printf("\n"); return newSVuv(ret); }
    On reflection, it probably doesn't make a lot of sense to be wrapping mpfr_out_str. I'll probably just leave Rmpfr_out_str as it is, and document the fact that calling it in a loop can lead to garbled output (and point out that it's safer to use Rmpfr_get_str).

    I mentioned elsewhere in this thread that Rmpfr_get_str currently can sometimes output one less digit than it ought (due to programmer error). The fix for that is to replace, in MPFR.xs (in the Rmpfr_deref2 function)
    mpfr_get_str(out, expptr, b, n_dig, *(INT2PTR(mpfr_t *, SvIV(SvRV(p))) +), SvUV(round));
    with
    mpfr_get_str(out, expptr, b, SvUV(n_digits), *(INT2PTR(mpfr_t *, SvIV( +SvRV(p)))), SvUV(round));
    That fix will find its way into the next version of Math::MPFR.

    Cheers,
    Rob