Andy, I want to temporarily, maybe permanently retract my last email. I found a bug(let) in the intialization of my unit test that appears to maybe account for all observed crashes, maybe. I'm re-verifying on multiple machines but this will take 24-48 hours. Basically, it looks like guile-2.9.2 is crash free (for the last 6 hours) on one os/compiler/glibc combination, I have to cross-check on another.
--linas On Sun, May 26, 2019 at 8:40 AM Linas Vepstas <linasveps...@gmail.com> wrote: > Hi Andy, > > Thanks! I just tried out the master branch of guile in git (the one > tagged v2.9.2). It now passes all of my unit tests. So that's good! ... > More or less -- there's still some infrequent multi-threading bug(s). Let > me describe. > > My unit test just transitions C->guile->C and returns, in rapid > succession, in 20 threads. So, in pseudocode: > > SCM do_stuff(SCM a, SCM b) { > scm_to_utf8_string(a); > scm_to_int(b); > ... minor stuff... return scm_from_int(...); > } > scm_c_define_gsubr("do-things",2,0,0, do_stuff); > > void thing_doer(int thread_id) { > for (i=0; i=15000; i++) > char str[100]; > sprintf(str, "(do-things foo %d)", i); > scm_c_catch(scm_eval_string, str); > } > > main () { > for (int i=1; i<15; i++) // start 15 threads > std::thread(&thing_doer, i); > } > > I'm guessing the above code spends maybe 90% of its time bouncing between > guile and C. The string "(do-things foo 42)" changes each time in the loop, > so, not sure how the compile vs. interpret tradeoff is done. Either way, > its relatively trivial. Likewise, the do_stuff() C routine is fairly thin; > after decoding it's args, it doesn't do all that much (sub-microsecond of > computing). Based on old, old measurements, scm_eval_string really is the > primary CPU consumer, in the 20-microseconds range. Launching 15 threads > means that this thing is racing as fast as it can. > > Anyway, with guile-2.9.2, the above crashes after about 10-15 minutes, > either with memory corruption, or with segfault. I worried, so I retested > with guile-2.2.4 ... which also crashes, but much much less frequently: > seven times in 44 hours wall-clock time (so once ever 6 hours). Which is > still more than desired, but...OK. > > So where's the crash? No clue. Could be my code, could be guile. Since > there's a big difference between guile-2.2 and guile-2.9, I'm ready to > blame guile. I did try to run it with `valgrind --tool helgrind` and got an > ocean of complaints about guile GC, which are probably harmless. I haven't > tried to dig deeper yet. > > -- Linas > > > On Thu, May 23, 2019 at 2:28 PM Andy Wingo <wi...@pobox.com> wrote: > >> Hi! >> >> On Thu 06 Dec 2018 06:21, Linas Vepstas <linasveps...@gmail.com> writes: >> >> > After sending the email below, I scanned the guile-devel archives, >> > and I see Thomas Morley talking about Lilypond performance. >> > The example program he offers up caught my eye: nested deep >> > in a loop is this: >> > >> > (eval-string "'(a b c)") >> >> In this case I believe Guile 2.9 / 3 should be significantly faster than >> 2.2, because `eval' is compiled to native code rather than bytecode. My >> measurements showed it to be on par with the hand-optimized C >> implementation from 1.8 and before. Depends of course on how much the >> expander is part of your workload, there are differences relative to >> Guile 1.8. Anyway, thanks for the note and I just wanted to mention >> this point. >> >> Regarding Scheme -> C++ transitions, there is the possibility that this >> too could be much faster with Guile 2.9.x given that these calls are now >> JIT-compiled instead of interpreted. We'll have to see. >> >> Cheers, >> >> Andy >> > > > -- > cassette tapes - analog TV - film cameras - you > -- cassette tapes - analog TV - film cameras - you