On 03/03/2016 12:08 AM, Clément Pit--Claudel wrote: > I've reattached both profiles. Hi, I've looked further into this. Comparing the profiles, there seems to be two significant differences: 1. ‘deliver_user_signal’ gets called constantly in the slow case, with many calls to ‘x_catch_errors_with_handler’, ‘x_catch_errors_with_handler’, ‘x_had_errors_p’, and ‘x_uncatch_errors’; there are few to no such calls in the fast case. 2. font_list_entities constantly calls xfont_list in the slow case, but not in the fast case: In the slow case: ----------------------------------------------- 0.04 1.01 554734/554734 font_find_for_lface [14] [16] 11.0 0.04 1.01 554734 font_list_entities [16] 0.04 0.91 554734/554734 xfont_list [17] 0.02 0.00 554734/2778892 Fnreverse [45] 0.00 0.02 1109468/1109469 assoc_no_quit [96] 0.01 0.00 1109468/1109470 xfont_get_cache [121] 0.01 0.00 555016/1289625 Fcons [80] 0.00 0.00 141/141 xftfont_list [212] 0.00 0.00 141/45490 concat [103] 0.00 0.00 141/138863 copy_font_spec [78] 0.00 0.00 141/6814 Fvconcat [832] ----------------------------------------------- In the fast case: ----------------------------------------------- 0.06 0.41 1533134/1533134 font_find_for_lface [13] [25] 14.8 0.06 0.41 1533134 font_list_entities [25] 0.02 0.31 3066268/3066269 assoc_no_quit [29] 0.07 0.00 1533134/7672938 Fnreverse [28] 0.02 0.00 1534750/3266575 Fcons [62] 0.00 0.00 347/347 xftfont_list [209] 0.00 0.00 461/461 xfont_list [245] 0.00 0.00 808/385139 copy_font_spec [50] 0.00 0.00 347/56861 concat [111] 0.00 0.00 3066268/3066270 xfont_get_cache [605] 0.00 0.00 347/5788 Fvconcat [739] ----------------------------------------------- The difference there is this line in the slow profile: 0.04 0.91 554734/554734 xfont_list [17] (compare to this line:) 0.00 0.00 461/461 xfont_list [245] font_list_entities is in src/font.c; it call xfont_list here (old code): Lisp_Object copy; val = driver_list->driver->list (f, scratch_font_spec); // ← HERE if (NILP (val)) val = zero_vector; else val = Fvconcat (1, &val); copy = copy_font_spec (scratch_font_spec); ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache))); Here is the new code: val = driver_list->driver->list (f, scratch_font_spec); if (!NILP (val)) { Lisp_Object copy = copy_font_spec (scratch_font_spec); val = Fvconcat (1, &val); ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache))); } The commit message didn't explain why it was a good thing to not add an empty vector to the cache. I'm a bit stuck at this point. I'm not sure how 1 and 2 are connected. Suggestions? Clément.