From: ludovic.courtes@laas.fr (Ludovic Courtès)
To: Guile-Devel <guile-devel@gnu.org>
Subject: Re: Unbuffered socket I/O
Date: Mon, 26 Feb 2007 15:07:43 +0100 [thread overview]
Message-ID: <877iu59fm8.fsf@laas.fr> (raw)
In-Reply-To: <87abz13kxl.fsf@zip.com.au> (Kevin Ryde's message of "Mon, 26 Feb 2007 09:57:10 +1100")
[-- Attachment #1: Type: text/plain, Size: 1489 bytes --]
Hi,
Kevin Ryde <user42@zip.com.au> writes:
> ludovic.courtes@laas.fr (Ludovic Courtès) writes:
>> #define SCM_SOCK_FD_TO_PORT(fd) \
>> scm_fdes_to_port (fd, "r", sym_socket)
>
> That's an incompatible change, I think, since it can leave unflushed
> data where previously it went straight out.
Right. That's an incompatible change if the _output_ is buffered.
Input can be buffered, though, without this being visible by users.
Fortunately, port buffering doesn't have to be symmetrical (although the
API allowing to do that is internal---actually, we might want to expose
and document `scm_fport_buffer_add ()'). Thus, I propose the following
change, where sockets are turned into ports whose output is left
unbuffered and whose input is buffered. Again, this has no visible
effect on user programs AFAICS.
I tried it with TCP server-side sockets and the performance impact is
_huge_. Actually, it seems even hard to write a TCP server without this
because it takes so long to read a single octet that clients may
time-out before the server is done receiving their request! (I observed
this with RPC server/clients)
BTW, do you know what the purpose of `fport_wait_for_input ()' is? It
does nothing for O_NONBLOCK streams and waits for events otherwise.
Since, for blocking streams, `read ()' does not return until either EOF
is reached or at least one octet was read, `fport_wait_for_input ()'
seems redundant.
Thanks,
Ludovic.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Patch providing socket input buffering. --]
[-- Type: text/x-patch, Size: 3183 bytes --]
--- orig/libguile/fports.c
+++ mod/libguile/fports.c
@@ -90,11 +90,11 @@
/* default buffer size, used if the O/S won't supply a value. */
static const size_t default_buffer_size = 1024;
-/* create FPORT buffer with specified sizes (or -1 to use default size or
- 0 for no buffer. */
-static void
-scm_fport_buffer_add (SCM port, long read_size, int write_size)
-#define FUNC_NAME "scm_fport_buffer_add"
+/* Create FPORT buffer with specified sizes (or -1 to use default size or
+ 0 for no buffer). */
+void
+scm_i_fport_buffer_add (SCM port, long read_size, long write_size)
+#define FUNC_NAME "scm_i_fport_buffer_add"
{
scm_t_port *pt = SCM_PTAB_ENTRY (port);
@@ -212,7 +212,7 @@
if (pt->write_buf != &pt->shortbuf)
scm_gc_free (pt->write_buf, pt->write_buf_size, "port buffer");
- scm_fport_buffer_add (port, csize, csize);
+ scm_i_fport_buffer_add (port, csize, csize);
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
@@ -465,9 +465,9 @@
pt->rw_random = SCM_FDES_RANDOM_P (fdes);
SCM_SETSTREAM (port, fp);
if (mode_bits & SCM_BUF0)
- scm_fport_buffer_add (port, 0, 0);
+ scm_i_fport_buffer_add (port, 0, 0);
else
- scm_fport_buffer_add (port, -1, -1);
+ scm_i_fport_buffer_add (port, -1, -1);
}
SCM_SET_FILENAME (port, name);
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
--- orig/libguile/fports.h
+++ mod/libguile/fports.h
@@ -60,7 +60,8 @@
SCM_API SCM scm_i_fdes_to_port (int fdes, long mode_bits, SCM name);
SCM_API int scm_i_fport_truncate (SCM, SCM);
SCM_API SCM scm_i_fport_seek (SCM, SCM, int);
-
+SCM_API void scm_i_fport_buffer_add (SCM port, long read_size,
+ long write_size);
#endif /* SCM_FPORTS_H */
--- orig/libguile/socket.c
+++ mod/libguile/socket.c
@@ -403,9 +403,26 @@
#endif /* HAVE_IPV6 */
+\f
+/* Sockets. */
+
SCM_SYMBOL (sym_socket, "socket");
-#define SCM_SOCK_FD_TO_PORT(fd) scm_fdes_to_port (fd, "r+0", sym_socket)
+/* Size of the input buffer of socket ports. */
+#define SCM_SOCKET_INPUT_BUFFER_SIZE 4096
+
+
+/* Return a socket with buffered input and unbufferred output. */
+static inline SCM
+socket_to_port (int fd)
+{
+ SCM port;
+
+ port = scm_fdes_to_port (fd, "r+0", sym_socket);
+ scm_i_fport_buffer_add (port, SCM_SOCKET_INPUT_BUFFER_SIZE, 0);
+
+ return port;
+}
SCM_DEFINE (scm_socket, "socket", 3, 0, 0,
(SCM family, SCM style, SCM proto),
@@ -429,7 +446,7 @@
scm_to_int (proto));
if (fd == -1)
SCM_SYSERROR;
- return SCM_SOCK_FD_TO_PORT (fd);
+ return socket_to_port (fd);
}
#undef FUNC_NAME
@@ -451,7 +468,7 @@
if (socketpair (fam, scm_to_int (style), scm_to_int (proto), fd) == -1)
SCM_SYSERROR;
- return scm_cons (SCM_SOCK_FD_TO_PORT (fd[0]), SCM_SOCK_FD_TO_PORT (fd[1]));
+ return scm_cons (socket_to_port (fd[0]), socket_to_port (fd[1]));
}
#undef FUNC_NAME
#endif
@@ -1312,7 +1329,7 @@
newfd = accept (fd, addr, &addr_size);
if (newfd == -1)
SCM_SYSERROR;
- newsock = SCM_SOCK_FD_TO_PORT (newfd);
+ newsock = socket_to_port (newfd);
address = _scm_from_sockaddr (addr, addr_size, FUNC_NAME);
return scm_cons (newsock, address);
}
[-- Attachment #3: Type: text/plain, Size: 143 bytes --]
_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel
next prev parent reply other threads:[~2007-02-26 14:07 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-02-23 17:09 Unbuffered socket I/O Ludovic Courtès
2007-02-23 22:36 ` Neil Jerram
2007-02-25 22:57 ` Kevin Ryde
2007-02-26 14:07 ` Ludovic Courtès [this message]
2007-02-26 20:32 ` Neil Jerram
2007-02-26 23:35 ` Kevin Ryde
2007-02-27 9:11 ` Ludovic Courtès
2007-02-28 21:24 ` Kevin Ryde
2007-03-01 9:10 ` Ludovic Courtès
2007-03-04 23:48 ` Kevin Ryde
2007-03-07 0:20 ` Kevin Ryde
2007-03-07 0:30 ` Kevin Ryde
2007-03-07 4:45 ` Kevin Ryde
2007-03-07 9:40 ` Ludovic Courtès
2007-02-26 23:27 ` Kevin Ryde
2007-02-28 9:47 ` Ludovic Courtès
2007-02-28 20:59 ` Kevin Ryde
2007-03-01 10:44 ` Ludovic Courtès
2007-03-05 23:15 ` Kevin Ryde
2007-08-07 16:01 ` Ludovic Courtès
2007-05-13 17:13 ` `scm_std_select ()' call in `fport_wait_for_input ()' Ludovic Courtès
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=877iu59fm8.fsf@laas.fr \
--to=ludovic.courtes@laas.fr \
--cc=guile-devel@gnu.org \
/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).