I got curious about the performance details of the compiler tower and
had to augment guild compile and compile-file in (system base compile)
to look at it. I added an option to collect statistical profiling data
with the statprof module and write a the data to a file (in flat
format). Figured the addition might be useful for anyone trying to
improve the performance of one of the compilers at some point (say,
someone adding a new language compiler to guile).

One accesses it with guild compile using the -s or --stats option. For example,

    guild compile -s SFILE foo.scm

And in the compile-file procedure with a new keyword parameter #:stats-file

The patch is attached. Note, collecting all the right output to put in
the file requires the patch for bug #26172
(https://debbugs.gnu.org/cgi/bugreport.cgi?bug=26172). Otherwise, the
last three lines of the statprof flat profile get written to
(current-output-port) instead of to the file.


Freja Nordsiek
From 8ce790606d2e8a68946ee4007e979530bdd37d00 Mon Sep 17 00:00:00 2001
From: Freja Nordsiek <fnord...@gmail.com>
Date: Sun, 26 Mar 2017 13:01:09 +0200
Subject: [PATCH] Add option to collect and write statprof data of compilation
 to a file.

* module/system/base/compile.scm (compile-file): Added stats-file option to
  collect and write statistical profiling data of the compilation using
  (statprof) to a file.
* module/scripts/compile.scm (compile): Added a commandline option to
  use the new stats-file option in (system base compile)'s compile-file
  procedure.
* doc/ref/api-evaluation.texi: Updated documentation on compilation to
  reflect the new option.
---
 doc/ref/api-evaluation.texi    | 11 +++++++++++
 module/scripts/compile.scm     | 17 ++++++++++++++++-
 module/system/base/compile.scm | 28 ++++++++++++++++++++--------
 3 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/doc/ref/api-evaluation.texi b/doc/ref/api-evaluation.texi
index 3a3e9e6..202ebdc 100644
--- a/doc/ref/api-evaluation.texi
+++ b/doc/ref/api-evaluation.texi
@@ -683,6 +683,12 @@ Config, %host-type}).  Target must be a valid GNU triplet, such as
 @code{armv5tel-unknown-linux-gnueabi} (@pxref{Specifying Target
 Triplets,,, autoconf, GNU Autoconf Manual}).
 
+@item -s @var{sfile}
+@itemx --stats=@var{sfile}
+Write profiling data for the compiler to file @var{sfile}. Statistical
+profiling data is collected using the @code{(statprof)} module and
+written in a flat style. @xref{Statprof}, for documentation.
+
 @end table
 
 Each @var{file} is assumed to be UTF-8-encoded, unless it contains a
@@ -707,6 +713,7 @@ the Virtual Machine}.
 @deffn {Scheme Procedure} compile-file file [#:output-file=#f] @
                           [#:from=(current-language)] [#:to='rtl] @
                           [#:env=(default-environment from)] @
+                          [#:stats-file=#f] @
                           [#:opts='()] @
                           [#:canonicalization='relative]
 Compile the file named @var{file}.
@@ -719,6 +726,10 @@ computed by @code{(compiled-file-name @var{file})}.
 @xref{Compiling to the Virtual Machine}, for more information on these
 options, and on @var{env} and @var{opts}.
 
+If @var{stats-file} is set and only one file is being compiled, statistical
+profiling data of the compiler is taken during compilation and the results to
+the file @var{stats-file} in a flat format. @xref{Statprof}, for documentation.
+
 As with @command{guild compile}, @var{file} is assumed to be
 UTF-8-encoded unless it contains a coding declaration.
 @end deffn
diff --git a/module/scripts/compile.scm b/module/scripts/compile.scm
index 939fb25..f69dcef 100644
--- a/module/scripts/compile.scm
+++ b/module/scripts/compile.scm
@@ -130,7 +130,13 @@
                 (lambda (opt name arg result)
                   (if (assoc-ref result 'target)
                       (fail "`--target' option cannot be specified more than once")
-                      (alist-cons 'target arg result))))))
+                      (alist-cons 'target arg result))))
+
+        (option '(#\s "stats") #t #f
+		(lambda (opt name arg result)
+		  (if (assoc-ref result 'stats-file)
+		      (fail "`--stats' option cannot be specified more than once")
+		      (alist-cons 'stats-file arg result))))))
 
 (define (parse-args args)
   "Parse argument list @var{args} and return an alist with all the relevant
@@ -202,6 +208,7 @@ There is NO WARRANTY, to the extent permitted by law.~%"))
          (target          (or (assoc-ref options 'target) %host-type))
 	 (input-files     (assoc-ref options 'input-files))
 	 (output-file     (assoc-ref options 'output-file))
+         (stats-file      (assoc-ref options 'stats-file))
 	 (load-path       (assoc-ref options 'load-path)))
     (if (or help? (null? input-files))
         (begin
@@ -221,6 +228,7 @@ Compile each Guile source file FILE into a Guile object.
   -f, --from=LANG      specify a source language other than `scheme'
   -t, --to=LANG        specify a target language other than `bytecode'
   -T, --target=TRIPLET produce bytecode for host TRIPLET
+  -s, --stats=SFILE    write flat statprof data for compilation to SFILE
 
 Note that auto-compilation will be turned off.
 
@@ -237,6 +245,12 @@ Report bugs to <~A>.~%"
         (fail "`-o' option can only be specified "
               "when compiling a single file"))
 
+    (if (and stats-file
+             (or (null? input-files)
+                 (not (null? (cdr input-files)))))
+        (fail "`-s' option can only be specified "
+              "when compiling a single file"))
+
     ;; Install a SIGINT handler.  As a side effect, this gives unwind
     ;; handlers an opportunity to run upon SIGINT; this includes that of
     ;; 'call-with-output-file/atomic', called by 'compile-file', which
@@ -252,6 +266,7 @@ Report bugs to <~A>.~%"
                             (lambda ()
                               (compile-file file
                                             #:output-file output-file
+                                            #:stats-file stats-file
                                             #:from from
                                             #:to to
                                             #:opts compile-opts))))))
diff --git a/module/system/base/compile.scm b/module/system/base/compile.scm
index c110512..09d2dce 100644
--- a/module/system/base/compile.scm
+++ b/module/system/base/compile.scm
@@ -134,6 +134,7 @@
 
 (define* (compile-file file #:key
                        (output-file #f)
+                       (stats-file #f)
                        (from (current-language))
                        (to 'bytecode)
                        (env (default-environment from))
@@ -144,18 +145,29 @@
                      (error "failed to create path for auto-compiled file"
                             file)))
            (in (open-input-file file))
-           (enc (file-encoding in)))
+           (enc (file-encoding in))
+           (compile-proc
+             (lambda ()
+               (call-with-output-file/atomic
+                comp
+                (lambda (port)
+                  ((language-printer (ensure-language to))
+                   (read-and-compile in #:env env #:from from #:to to #:opts
+                                     (cons* #:to-file? #t opts))
+                   port))
+                file))))
       ;; Choose the input encoding deterministically.
       (set-port-encoding! in (or enc "UTF-8"))
 
       (ensure-directory (dirname comp))
-      (call-with-output-file/atomic comp
-        (lambda (port)
-          ((language-printer (ensure-language to))
-           (read-and-compile in #:env env #:from from #:to to #:opts
-                             (cons* #:to-file? #t opts))
-           port))
-        file)
+      (if stats-file
+          (begin
+            (ensure-directory (dirname stats-file))
+            (call-with-output-file/atomic stats-file
+                                          (lambda (port)
+                                            ((@ (statprof) statprof) compile-proc #:port port))
+                                          file))
+          (compile-proc))
       comp)))
 
 (define* (compile-and-load file #:key (from (current-language)) (to 'value)
-- 
2.9.3

Reply via email to