unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Mark H Weaver <mhw@netris.org>
To: Chris Vine <vine35792468@gmail.com>
Cc: guile-devel@gnu.org
Subject: Re: Unexpectedly low read/write performance of open-pipe
Date: Tue, 16 Apr 2019 17:42:22 -0400	[thread overview]
Message-ID: <87ftqh62zq.fsf@netris.org> (raw)
In-Reply-To: <87d0lusoxb.fsf@netris.org> (Mark H. Weaver's message of "Tue, 09 Apr 2019 20:07:17 -0400")

[-- Attachment #1: Type: text/plain, Size: 854 bytes --]

> Earlier, I wrote:
>> I'm not sure off-hand what would be required to re-implement custom
>> ports in suspendable Scheme code.
>
> I finally dug into this code, and was delighted to find that Andy Wingo
> has already laid the groundwork to avoid going through C code in our
> custom port handlers, in commit 8bad621fec65d58768a38661278165ae259fabce
> from April 2016:
>
>   https://git.savannah.gnu.org/cgit/guile.git/commit/?id=8bad621fec65d58768a38661278165ae259fabce
>
> Given this, I think it will be fairly straightforward to modify our
> custom ports to be suspendable.  Likewise, I see no difficulty in
> implementing a suspendable version of 'get-bytevector-some'.
>
> I'll work on it.

Here are preliminary patches to implement suspendable custom ports and
'get-bytevector-some', although I haven't yet given them much testing.

        Mark



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: [PATCH] DRAFT: Add a suspendable implementation of 'get-bytevector-some' --]
[-- Type: text/x-patch, Size: 1936 bytes --]

From 271cbbc3acc40926c8311e8dcca757285a53f00d Mon Sep 17 00:00:00 2001
From: Mark H Weaver <mhw@netris.org>
Date: Sun, 14 Apr 2019 17:43:30 -0400
Subject: [PATCH] DRAFT: Add a suspendable implementation of
 'get-bytevector-some'.

---
 module/ice-9/suspendable-ports.scm | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/module/ice-9/suspendable-ports.scm b/module/ice-9/suspendable-ports.scm
index a366c8b9c..d91ffd3c1 100644
--- a/module/ice-9/suspendable-ports.scm
+++ b/module/ice-9/suspendable-ports.scm
@@ -1,5 +1,5 @@
 ;;; Ports, implemented in Scheme
-;;; Copyright (C) 2016 Free Software Foundation, Inc.
+;;; Copyright (C) 2016, 2019 Free Software Foundation, Inc.
 ;;;
 ;;; This library is free software: you can redistribute it and/or modify
 ;;; it under the terms of the GNU Lesser General Public License as
@@ -292,6 +292,19 @@
        ((< (- count pos) (port-read-buffering port)) (buffer-and-fill pos))
        (else (fill-directly pos))))))
 
+(define (get-bytevector-some port)
+  (call-with-values (lambda () (fill-input port 1 'binary))
+    (lambda (buf cur buffered)
+      (if (zero? buffered)
+          (begin
+            (set-port-buffer-has-eof?! buf #f)
+            the-eof-object)
+          (let ((result (make-bytevector buffered)))
+            (bytevector-copy! (port-buffer-bytevector buf) cur
+                              result 0 buffered)
+            (set-port-buffer-cur! buf (+ cur buffered))
+            result)))))
+
 (define (put-u8 port byte)
   (let* ((buf (port-write-buffer port))
          (bv (port-buffer-bytevector buf))
@@ -702,7 +715,7 @@
      read-char peek-char force-output close-port
      accept connect)
     ((ice-9 binary-ports)
-     get-u8 lookahead-u8 get-bytevector-n
+     get-u8 lookahead-u8 get-bytevector-n get-bytevector-some
      put-u8 put-bytevector)
     ((ice-9 textual-ports)
      put-char put-string)
-- 
2.21.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: [PATCH] DRAFT: Make custom binary ports suspendable --]
[-- Type: text/x-patch, Size: 10556 bytes --]

From 57b1cb09a9c7b553ce35782605016430a355e237 Mon Sep 17 00:00:00 2001
From: Mark H Weaver <mhw@netris.org>
Date: Sun, 14 Apr 2019 17:30:40 -0400
Subject: [PATCH] DRAFT: Make custom binary ports suspendable.

---
 libguile/r6rs-ports.c         | 136 +++++++++++++++++++++-------------
 module/ice-9/binary-ports.scm |  24 +++++-
 2 files changed, 107 insertions(+), 53 deletions(-)

diff --git a/libguile/r6rs-ports.c b/libguile/r6rs-ports.c
index c1cbbdf30..577bcdffd 100644
--- a/libguile/r6rs-ports.c
+++ b/libguile/r6rs-ports.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2009, 2010, 2011, 2013-2015, 2018 Free Software Foundation, Inc.
+/* Copyright (C) 2009-2011, 2013-2015, 2018, 2019
+ *   Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -289,24 +290,6 @@ make_custom_binary_input_port (SCM read_proc, SCM get_position_proc,
                                         (scm_t_bits) stream);
 }
 
-static size_t
-custom_binary_input_port_read (SCM port, SCM dst, size_t start, size_t count)
-#define FUNC_NAME "custom_binary_input_port_read"
-{
-  struct custom_binary_port *stream = (void *) SCM_STREAM (port);
-  SCM octets;
-  size_t c_octets;
-
-  octets = scm_call_3 (stream->read, dst, scm_from_size_t (start),
-                       scm_from_size_t (count));
-  c_octets = scm_to_size_t (octets);
-  if (c_octets > count)
-    scm_out_of_range (FUNC_NAME, octets);
-
-  return c_octets;
-}
-#undef FUNC_NAME
-
 
 SCM_DEFINE (scm_make_custom_binary_input_port,
 	    "make-custom-binary-input-port", 5, 0, 0,
@@ -317,6 +300,9 @@ SCM_DEFINE (scm_make_custom_binary_input_port,
 	    "index where octets should be written, and an octet count.")
 #define FUNC_NAME s_scm_make_custom_binary_input_port
 {
+  /* Ensure that custom binary ports are initialized. */
+  scm_c_resolve_module ("ice-9 binary-ports");
+  
   SCM_VALIDATE_STRING (1, id);
   SCM_VALIDATE_PROC (2, read_proc);
 
@@ -340,9 +326,11 @@ static inline void
 initialize_custom_binary_input_ports (void)
 {
   custom_binary_input_port_type =
-    scm_make_port_type ("r6rs-custom-binary-input-port",
-			custom_binary_input_port_read, NULL);
+    scm_make_port_type ("r6rs-custom-binary-input-port", NULL, NULL);
 
+  scm_set_port_scm_read (custom_binary_input_port_type,
+                         scm_c_private_ref ("ice-9 binary-ports",
+                                            "custom-binary-port-read!"));
   scm_set_port_seek (custom_binary_input_port_type, custom_binary_port_seek);
   scm_set_port_random_access_p (custom_binary_input_port_type,
                                 custom_binary_port_random_access_p);
@@ -892,28 +880,6 @@ make_custom_binary_output_port (SCM write_proc, SCM get_position_proc,
                                         (scm_t_bits) stream);
 }
 
-/* Flush octets from BUF to the backing store.  */
-static size_t
-custom_binary_output_port_write (SCM port, SCM src, size_t start, size_t count)
-#define FUNC_NAME "custom_binary_output_port_write"
-{
-  struct custom_binary_port *stream = (void *) SCM_STREAM (port);
-  size_t written;
-  SCM result;
-
-  result = scm_call_3 (stream->write, src, scm_from_size_t (start),
-                       scm_from_size_t (count));
-
-  written = scm_to_size_t (result);
-  if (written > count)
-    scm_wrong_type_arg_msg (FUNC_NAME, 0, result,
-                            "R6RS custom binary output port `write!' "
-                            "returned a incorrect integer");
-
-  return written;
-}
-#undef FUNC_NAME
-
 
 SCM_DEFINE (scm_make_custom_binary_output_port,
 	    "make-custom-binary-output-port", 5, 0, 0,
@@ -924,6 +890,9 @@ SCM_DEFINE (scm_make_custom_binary_output_port,
 	    "index where octets should be written, and an octet count.")
 #define FUNC_NAME s_scm_make_custom_binary_output_port
 {
+  /* Ensure that custom binary ports are initialized. */
+  scm_c_resolve_module ("ice-9 binary-ports");
+  
   SCM_VALIDATE_STRING (1, id);
   SCM_VALIDATE_PROC (2, write_proc);
 
@@ -947,9 +916,11 @@ static inline void
 initialize_custom_binary_output_ports (void)
 {
   custom_binary_output_port_type =
-    scm_make_port_type ("r6rs-custom-binary-output-port",
-			NULL, custom_binary_output_port_write);
+    scm_make_port_type ("r6rs-custom-binary-output-port", NULL, NULL);
 
+  scm_set_port_scm_write (custom_binary_output_port_type,
+                          scm_c_private_ref ("ice-9 binary-ports",
+                                             "custom-binary-port-write!"));
   scm_set_port_seek (custom_binary_output_port_type, custom_binary_port_seek);
   scm_set_port_random_access_p (custom_binary_output_port_type,
                                 custom_binary_port_random_access_p);
@@ -996,6 +967,9 @@ SCM_DEFINE (scm_make_custom_binary_input_output_port,
             "written, and an octet count.")
 #define FUNC_NAME s_scm_make_custom_binary_input_output_port
 {
+  /* Ensure that custom binary ports are initialized. */
+  scm_c_resolve_module ("ice-9 binary-ports");
+  
   SCM_VALIDATE_STRING (1, id);
   SCM_VALIDATE_PROC (2, read_proc);
   SCM_VALIDATE_PROC (3, write_proc);
@@ -1020,10 +994,14 @@ static inline void
 initialize_custom_binary_input_output_ports (void)
 {
   custom_binary_input_output_port_type =
-    scm_make_port_type ("r6rs-custom-binary-input/output-port",
-			custom_binary_input_port_read,
-			custom_binary_output_port_write);
-
+    scm_make_port_type ("r6rs-custom-binary-input/output-port", NULL, NULL);
+
+  scm_set_port_scm_read (custom_binary_input_output_port_type,
+                         scm_c_private_ref ("ice-9 binary-ports",
+                                            "custom-binary-port-read!"));
+  scm_set_port_scm_write (custom_binary_input_output_port_type,
+                          scm_c_private_ref ("ice-9 binary-ports",
+                                             "custom-binary-port-write!"));
   scm_set_port_seek (custom_binary_input_output_port_type,
                      custom_binary_port_seek);
   scm_set_port_random_access_p (custom_binary_input_output_port_type,
@@ -1035,6 +1013,56 @@ initialize_custom_binary_input_output_ports (void)
 
 \f
 
+/* Internal accessors needed by 'custom-binary-port-read!' and
+   'custom-binary-port-write!'.  */
+
+SCM_INTERNAL SCM scm_i_custom_binary_port_reader (SCM);
+SCM_DEFINE (scm_i_custom_binary_port_reader,
+            "custom-binary-port-reader", 1, 0, 0,
+            (SCM port),
+            "Return the 'read!' procedure associated with PORT, "
+            "which must be custom binary input or input/output port.")
+#define FUNC_NAME s_scm_i_custom_binary_port_reader
+{
+  SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
+
+  if (SCM_PORT_TYPE (port) == custom_binary_input_port_type ||
+      SCM_PORT_TYPE (port) == custom_binary_input_output_port_type)
+    {
+      struct custom_binary_port *stream = (void *) SCM_STREAM (port);
+      return stream->read;
+    }
+  else
+    scm_wrong_type_arg_msg (FUNC_NAME, 1, port,
+                            "custom binary input or input/output port");
+}
+#undef FUNC_NAME
+
+SCM_INTERNAL SCM scm_i_custom_binary_port_writer (SCM);
+SCM_DEFINE (scm_i_custom_binary_port_writer,
+            "custom-binary-port-writer", 1, 0, 0,
+            (SCM port),
+            "Return the 'write!' procedure associated with PORT, "
+            "which must be custom binary output or input/output port.")
+#define FUNC_NAME s_scm_i_custom_binary_port_writer
+{
+  SCM_VALIDATE_BINARY_OUTPUT_PORT (1, port);
+
+  if (SCM_PORT_TYPE (port) == custom_binary_output_port_type ||
+      SCM_PORT_TYPE (port) == custom_binary_input_output_port_type)
+    {
+      struct custom_binary_port *stream = (void *) SCM_STREAM (port);
+      return stream->write;
+    }
+  else
+    scm_wrong_type_arg_msg (FUNC_NAME, 1, port,
+                            "custom binary output or input/output port");
+}
+#undef FUNC_NAME
+
+
+\f
+
 /* Transcoded ports.  */
 
 static scm_t_port_type *transcoded_port_type = 0;
@@ -1160,15 +1188,19 @@ scm_register_r6rs_ports (void)
 			    NULL);
 
   initialize_bytevector_input_ports ();
-  initialize_custom_binary_input_ports ();
   initialize_bytevector_output_ports ();
-  initialize_custom_binary_output_ports ();
-  initialize_custom_binary_input_output_ports ();
   initialize_transcoded_ports ();
 }
 
 void
 scm_init_r6rs_ports (void)
 {
+  /* We postpone registering custom binary ports until (ice-9 binary-ports)
+   * is loaded, because these custom port types depend on Scheme procedures
+   * defined there.  */
+  initialize_custom_binary_input_ports ();
+  initialize_custom_binary_output_ports ();
+  initialize_custom_binary_input_output_ports ();
+
 #include "libguile/r6rs-ports.x"
 }
diff --git a/module/ice-9/binary-ports.scm b/module/ice-9/binary-ports.scm
index e0da3df1a..6389c9be8 100644
--- a/module/ice-9/binary-ports.scm
+++ b/module/ice-9/binary-ports.scm
@@ -1,6 +1,6 @@
 ;;;; binary-ports.scm --- Binary IO on ports
 
-;;;;	Copyright (C) 2009, 2010, 2011, 2013 Free Software Foundation, Inc.
+;;;; Copyright (C) 2009-2011, 2013, 2019 Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -45,6 +45,28 @@
             make-custom-binary-output-port
             make-custom-binary-input/output-port))
 
+(define (custom-binary-port-read! port bv start count)
+  (let* ((read! (custom-binary-port-reader port))
+         (result (read! bv start count)))
+    (unless (and (exact-integer? result)
+                 (<= 0 result count))
+      (scm-error 'out-of-range #f
+                 "custom port 'read!' (~S) returned value out of range; expected an exact integer between 0 and ~A, got ~A"
+                 (list read! count result)
+                 (list result)))
+    result))
+
+(define (custom-binary-port-write! port bv start count)
+  (let* ((write! (custom-binary-port-writer port))
+         (result (write! bv start count)))
+    (unless (and (exact-integer? result)
+                 (<= 0 result count))
+      (scm-error 'out-of-range #f
+                 "custom port 'write!' (~S) returned value out of range; expected an exact integer between 0 and ~A, got ~A"
+                 (list write! count result)
+                 (list result)))
+    result))
+
 ;; Note that this extension also defines %make-transcoded-port, which is
 ;; not exported but is used by (rnrs io ports).
 
-- 
2.21.0


  reply	other threads:[~2019-04-16 21:42 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-07 18:28 Unexpectedly low read/write performance of open-pipe Rob Browning
2019-04-07 18:45 ` Rob Browning
2019-04-07 19:47   ` Rob Browning
2019-04-07 21:28     ` Rob Browning
2019-04-08 10:52       ` Mark H Weaver
2019-04-09  6:56         ` Rob Browning
2019-04-09  8:35           ` Mark H Weaver
2019-04-09  9:21             ` Chris Vine
2019-04-09 18:24               ` Mark H Weaver
2019-04-09 21:36                 ` Chris Vine
2019-04-10  0:07                 ` Mark H Weaver
2019-04-16 21:42                   ` Mark H Weaver [this message]
2019-04-09 18:33               ` Mark H Weaver
2019-04-17  4:02           ` Mark H Weaver
2019-04-21 16:22             ` Rob Browning
2019-04-22 18:39               ` Arne Babenhauserheide
2019-04-23  7:32 ` tomas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ftqh62zq.fsf@netris.org \
    --to=mhw@netris.org \
    --cc=guile-devel@gnu.org \
    --cc=vine35792468@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).