guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Improved string writing


From: Ludovic Courtès
Subject: [PATCH] Improved string writing
Date: Wed, 20 Apr 2005 14:46:52 +0200
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

Hi,

While running Guile 1.7.2 under `strace', I noticed the following
unpleasant thing:

  write(1, "\"", 1)                       = 1
  write(1, "h", 1)                        = 1
  write(1, "e", 1)                        = 1
  write(1, "l", 1)                        = 1
  write(1, "l", 1)                        = 1
  write(1, "o", 1)                        = 1
  write(1, "\"", 1)                       = 1

All these system calls for just writing the string "hello".  :-)

The patch below adds buffering in `iprin1' (print.c) so that regular
strings (i.e. strings that don't contain any special characters) can be
written with only one `write' system call, while other strings[*] may be
printed with only a few `write' system calls.

Note that `format' in (ice-9 format) uses `write-char', which
unfortunately leads to the same problem as above.  So this will have to
be fixed eventually too.

Please, let me know if the patch looks ok.

Thanks,
Ludovic.

[*] Test case: (list->string (map integer->char (iota 40))).



diff -ubB --show-c-function /home/ludo/tmp/guile-1.7.2/libguile/print.c\~ 
/home/ludo/tmp/guile-1.7.2/libguile/print.c
--- /home/ludo/tmp/guile-1.7.2/libguile/print.c~        2005-03-03 
23:12:33.000000000 +0100
+++ /home/ludo/tmp/guile-1.7.2/libguile/print.c 2005-04-20 14:09:14.000000000 
+0200
@@ -508,29 +508,57 @@ iprin1 (SCM exp, SCM port, scm_print_sta
            {
              size_t i, len;
              const char *data;
+             char *buffer;
+             size_t buffer_len, buffer_pos = 0;;
 
-             scm_putc ('"', port);
              len = scm_i_string_length (exp);
              data = scm_i_string_chars (exp);
+
+             /* Allocate a string buffer large enough for the common case of
+                a printable string.  */
+             buffer = alloca (len + 20);
+             buffer_len = len + 20;
+
+#define PUSH_TO_BUFFER(_chr)                                   \
+             do                                                \
+               {                                               \
+                 if (buffer_pos + 1 > buffer_len)              \
+                   {                                           \
+                     /* Flush BUFFER to PORT.  */              \
+                     scm_lfwrite (buffer, buffer_len, port);   \
+                     buffer_pos = 0;                           \
+                   }                                           \
+                                                               \
+                 buffer[buffer_pos++] = (_chr);                \
+               }                                               \
+             while (0)
+
+             PUSH_TO_BUFFER ('"');
              for (i = 0; i < len; ++i)
                {
                  unsigned char ch = data[i];
                  if ((ch < 32 && ch != '\n') || (127 <= ch && ch < 148))
                    {
                      static char const hex[]="0123456789abcdef";
-                     scm_putc ('\\', port);
-                     scm_putc ('x', port);
-                     scm_putc (hex [ch / 16], port);
-                     scm_putc (hex [ch % 16], port);
+                     PUSH_TO_BUFFER ('\\');
+                     PUSH_TO_BUFFER ('x');
+                     PUSH_TO_BUFFER (hex [ch / 16]);
+                     PUSH_TO_BUFFER (hex [ch % 16]);
                    }
                  else
                    {
                      if (ch == '"' || ch == '\\')
-                       scm_putc ('\\', port);
-                     scm_putc (ch, port);
+                       PUSH_TO_BUFFER ('\\');
+                     PUSH_TO_BUFFER (ch);
                    }
                }
-             scm_putc ('"', port);
+             PUSH_TO_BUFFER ('"');
+
+             if (buffer_pos > 0)
+               /* Flush BUFFER to PORT up to BUFFER_POS.  */
+               scm_lfwrite (buffer, buffer_pos, port);
+
+#undef PUSH_TO_BUFFER
              scm_remember_upto_here_1 (exp);
            }
          else




reply via email to

[Prev in Thread] Current Thread [Next in Thread]