[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 07/07: Speed up scm_c_write / scm_lfwrite
From: |
Andy Wingo |
Subject: |
[Guile-commits] 07/07: Speed up scm_c_write / scm_lfwrite |
Date: |
Tue, 24 May 2016 20:44:59 +0000 (UTC) |
wingo pushed a commit to branch master
in repository guile.
commit 47918f38d9da5fe8e7e3dd0e7cf133b14c5cf04f
Author: Andy Wingo <address@hidden>
Date: Tue May 24 22:42:51 2016 +0200
Speed up scm_c_write / scm_lfwrite
* libguile/ports-internal.h (scm_t_port): Add write_buf_aux field.
* libguile/ports.h (scm_port_auxiliary_write_buffer): New internal
decl.
* libguile/ports.c (AUXILIARY_WRITE_BUFFER_SIZE): New constant.
(initialize_port_buffers): Init aux write buf.
(scm_port_auxiliary_write_buffer): Lazily allocate an aux write
buffer.
(scm_c_write): Arrange to write through an aux buffer if the port is
unbuffered.
---
libguile/ports-internal.h | 1 +
libguile/ports.c | 50 ++++++++++++++++++++++++++++++++++++++++++---
libguile/ports.h | 1 +
3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/libguile/ports-internal.h b/libguile/ports-internal.h
index 7aabee7..d014415 100644
--- a/libguile/ports-internal.h
+++ b/libguile/ports-internal.h
@@ -312,6 +312,7 @@ struct scm_t_port
/* Port buffers. */
SCM read_buf;
SCM write_buf;
+ SCM write_buf_aux;
/* All ports have read and write buffers; an unbuffered port simply
has a one-byte buffer. However unreading bytes can expand the read
diff --git a/libguile/ports.c b/libguile/ports.c
index f58da4b..3dd729d 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -56,7 +56,7 @@
#include "libguile/strings.h"
#include "libguile/mallocs.h"
#include "libguile/validate.h"
-//#include "libguile/ports.h"
+#include "libguile/ports.h"
#include "libguile/ports-internal.h"
#include "libguile/vectors.h"
#include "libguile/weak-set.h"
@@ -109,6 +109,9 @@ static SCM sym_error;
static SCM sym_substitute;
static SCM sym_escape;
+/* See scm_port_auxiliary_write_buffer and scm_c_write. */
+static const size_t AUXILIARY_WRITE_BUFFER_SIZE = 256;
+
@@ -660,6 +663,7 @@ initialize_port_buffers (SCM port)
pt->read_buffering = read_buf_size;
pt->read_buf = make_port_buffer (port, read_buf_size);
pt->write_buf = make_port_buffer (port, write_buf_size);
+ pt->write_buf_aux = SCM_BOOL_F;
}
SCM
@@ -2647,6 +2651,23 @@ SCM_DEFINE (scm_port_write_buffer, "port-write-buffer",
1, 0, 0,
}
#undef FUNC_NAME
+SCM_DEFINE (scm_port_auxiliary_write_buffer, "port-auxiliary-write-buffer",
+ 1, 0, 0, (SCM port),
+ "Return the auxiliary write buffer for a port.")
+#define FUNC_NAME s_scm_port_auxiliary_write_buffer
+{
+ scm_t_port *pt;
+
+ SCM_VALIDATE_OPPORT (1, port);
+
+ pt = SCM_PORT (port);
+ if (scm_is_false (pt->write_buf_aux))
+ pt->write_buf_aux = make_port_buffer (port, AUXILIARY_WRITE_BUFFER_SIZE);
+
+ return pt->write_buf_aux;
+}
+#undef FUNC_NAME
+
@@ -2774,22 +2795,45 @@ scm_c_write (SCM port, const void *ptr, size_t size)
scm_t_port *pt;
SCM write_buf;
size_t written = 0;
+ int using_aux_buffer = 0;
const scm_t_uint8 *src = ptr;
SCM_VALIDATE_OPOUTPORT (1, port);
pt = SCM_PORT (port);
- write_buf = pt->write_buf;
if (pt->rw_random)
scm_end_input (port);
+ /* Imagine we are writing 40 bytes on an unbuffered port. If we were
+ writing from a bytevector we could pass that write directly to the
+ port. But since we aren't, we need to go through a bytevector, and
+ if we went through the port buffer we'd have to make 40 individual
+ calls to the write function. That would be terrible. Really we
+ need an intermediate bytevector. But, we shouldn't use a trick
+ analogous to what we do with expand-port-read-buffer!, because the
+ way we use the cur and end cursors doesn't seem to facilitate that.
+ So instead we buffer through an auxiliary write buffer if needed.
+ To avoid re-allocating this buffer all the time, we store it on the
+ port. It should never be left with buffered data.
+
+ Use of an auxiliary write buffer is triggered if the buffer is
+ smaller than the size we would make for an auxiliary write buffer,
+ and the write is bigger than the buffer. */
+ write_buf = pt->write_buf;
+ if (scm_port_buffer_size (write_buf) < size &&
+ scm_port_buffer_size (write_buf) < AUXILIARY_WRITE_BUFFER_SIZE)
+ {
+ using_aux_buffer = 1;
+ write_buf = scm_port_auxiliary_write_buffer (port);
+ }
+
while (written < size)
{
size_t did_put = scm_port_buffer_put (write_buf, src, size - written);
written += did_put;
src += did_put;
- if (scm_port_buffer_can_put (write_buf) == 0)
+ if (using_aux_buffer || scm_port_buffer_can_put (write_buf) == 0)
scm_i_write (port, write_buf);
}
}
diff --git a/libguile/ports.h b/libguile/ports.h
index 2ebcf06..13661e0 100644
--- a/libguile/ports.h
+++ b/libguile/ports.h
@@ -208,6 +208,7 @@ SCM_INTERNAL SCM scm_port_read (SCM port);
SCM_INTERNAL SCM scm_port_write (SCM port);
SCM_INTERNAL SCM scm_port_read_buffer (SCM port);
SCM_INTERNAL SCM scm_port_write_buffer (SCM port);
+SCM_INTERNAL SCM scm_port_auxiliary_write_buffer (SCM port);
/* Output. */
SCM_API void scm_putc (char c, SCM port);
- [Guile-commits] branch master updated (6bf7ec0 -> 47918f3), Andy Wingo, 2016/05/24
- [Guile-commits] 02/07: close-port implementation in sports, Andy Wingo, 2016/05/24
- [Guile-commits] 06/07: Speed golf on Scheme put-u8, put-bytevector, Andy Wingo, 2016/05/24
- [Guile-commits] 07/07: Speed up scm_c_write / scm_lfwrite,
Andy Wingo <=
- [Guile-commits] 01/07: Add force-output to sports, Andy Wingo, 2016/05/24
- [Guile-commits] 04/07: `put-bytevector' in Scheme, Andy Wingo, 2016/05/24
- [Guile-commits] 03/07: Wire up non-blocking support in sport writes, Andy Wingo, 2016/05/24
- [Guile-commits] 05/07: Add put-u8 implementation in Scheme, Andy Wingo, 2016/05/24