Subject: Re: bug#23967: 25.1.50; Slow compilation of ns-win.el

From: Noam Postavsky <[email-masked]>
Date: Wed, 13 Jul 2016 17:15:15 -0400

On Wed, Jul 13, 2016 at 10:55 AM, Eli Zaretskii <[email-masked]> wrote:
> This is a known problem.  The culprit is ucs-normalize.el
> (uni-decomposition is loaded when ucs-normalize is compiled).  It
> takes a long time to compile even with Emacs that already has the
> byte-compiled byte-compiler loaded into it.

I ran the profiler on a compilation of ucs-normalize.el and found 2
easy optimizations (ucs-normalize-block-compose-chars was using
with-temp-buffer in a loop, so I lifted the it out of the loop; using
regexp-opt-charset instead of regexp-opt saves some char-to-string
conversion, sorting, and duplicate deletion). The attached patch
brings the compilation down from 2.5 seconds to 0.8 seconds in my
normal running Emacs, and using the bootstrap-emacs command posted by
Lars (swapping ../lisp/international/ucs-normalize.el for
../lisp/term/ns-win.el) from 1m30s to 7s.

>  When compiling
> ucs-normalize with an interpreted byte-compiler, it takes ages (11 min
> on my Core i7).  And since ucs-normalize is now preloaded on OS X, we
> compile it with the interpreted byte-compiler, as we do with any other
> file that is preloaded on _some_ platform.
>
> Patches to solve this conundrum in some way are welcome.

Could we call `byte-compile' on the byte-compiler functions after loading them?
diff --git i/lisp/international/ucs-normalize.el w/lisp/international/ucs-normalize.el
index 4b364ee..c03ea50 100644
--- i/lisp/international/ucs-normalize.el
+++ w/lisp/international/ucs-normalize.el
@@ -263,7 +263,7 @@ ucs-normalize-combining-chars
 (defvar ucs-normalize-combining-chars-regexp nil
   "Regular expression to match sequence of combining characters.")
   (setq ucs-normalize-combining-chars-regexp
-  (eval-when-compile (concat (regexp-opt (mapcar 'char-to-string combining-chars)) "+")))
+        (eval-when-compile (concat (regexp-opt-charset combining-chars) "+")))
 
 (declare-function decomposition-translation-alist "ucs-normalize"
                   (decomposition-function))
@@ -396,20 +396,20 @@ ucs-normalize-block-compose-chars
 It includes Singletons, CompositionExclusions, and Non-Starter
 decomposition."
     (let (entries decomposition composition)
-      (mapc
-       (lambda (start-end)
-         (cl-do ((i (car start-end) (+ i 1))) ((> i (cdr start-end)))
-           (setq decomposition
-                 (string-to-list
-                  (with-temp-buffer
-                    (insert i)
-                    (translate-region 1 2 decomposition-translation)
-                    (buffer-string))))
-           (setq composition
-                 (ucs-normalize-block-compose-chars decomposition composition-predicate))
-           (when (not (equal composition (list i)))
-             (setq entries (cons i entries)))))
-       check-range)
+      (with-temp-buffer
+        (dolist (start-end check-range)
+          (cl-do ((i (car start-end) (+ i 1))) ((> i (cdr start-end)))
+            (setq decomposition
+                  (string-to-list
+                   (progn
+                     (erase-buffer)
+                     (insert i)
+                     (translate-region 1 2 decomposition-translation)
+                     (buffer-string))))
+            (setq composition
+                  (ucs-normalize-block-compose-chars decomposition composition-predicate))
+            (when (not (equal composition (list i)))
+              (setq entries (cons i entries))))))
       ;;(remove-duplicates
        (append entries
                ucs-normalize-composition-exclusions
@@ -431,7 +431,7 @@ ucs-normalize-block-compose-chars
     (setq hfs-nfc-quick-check-list (quick-check-list 'ucs-normalize-hfs-nfd-table t ))
 
   (defun quick-check-list-to-regexp (quick-check-list)
-    (regexp-opt (mapcar 'char-to-string (append quick-check-list combining-chars))))
+    (regexp-opt-charset (append quick-check-list combining-chars)))
 
   (defun quick-check-decomposition-list-to-regexp (quick-check-list)
     (concat (quick-check-list-to-regexp quick-check-list) "\\|[가-힣]"))