[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] scratch/raeburn-startup 913592c 14/17: Optimize reading of
From: |
Ken Raeburn |
Subject: |
[Emacs-diffs] scratch/raeburn-startup 913592c 14/17: Optimize reading of ASCII symbols from a .elc file. |
Date: |
Thu, 15 Dec 2016 11:33:19 +0000 (UTC) |
branch: scratch/raeburn-startup
commit 913592ce9b9b879dfedefd803035112de84dee32
Author: Ken Raeburn <address@hidden>
Commit: Ken Raeburn <address@hidden>
Optimize reading of ASCII symbols from a .elc file.
Normally, for each character read by read1, readchar is called, which
determines the kind of input function and selects a function to call
to read a byte, possibly calling it multiple times for multibyte
characters. If the input function is the symbol get-file-char,
readbyte_from_file must block input temporarily while reading. The
called function must also support a "pushback" operation.
This is a lot of work per byte and per character. Manually expanding
inline for this case lets us reduce redundant or unneeded checks. We
can also reduce the block/unblock calls, letting input normally stay
blocked from one getc call to the next.
* src/lread.c (read1): When reading a symbol name, if readcharfun is
Qget_file_char, use a separate do loop. Expand the main READCHAR
invocation into the relevant parts of readchar(). Expand the main
readbyte call of readchar used for ASCII characters into the relevant
parts of readbyte_from_file. Block input in this version of the loop,
unblocking temporarily only when needed.
---
src/lread.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 139 insertions(+), 21 deletions(-)
diff --git a/src/lread.c b/src/lread.c
index c9dc222..62a55e7 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -185,6 +185,8 @@ static int readbyte_from_string (int, Lisp_Object);
means that there's no unread character. */
static int unread_char;
+/* Note that this is expanded inline by hand in a branch of read1 for
+ performance reasons. */
static int
readchar (Lisp_Object readcharfun, bool *multibyte)
{
@@ -462,6 +464,8 @@ readbyte_for_lambda (int c, Lisp_Object readcharfun)
}
+/* Note that this is expanded inline by hand in a branch of read1 for
+ performance reasons. */
static int
readbyte_from_file (int c, Lisp_Object readcharfun)
{
@@ -3330,34 +3334,148 @@ read1 (Lisp_Object readcharfun, int *pch, bool
first_in_list)
{
char *end = read_buffer + read_buffer_size;
- do
+ if (EQ (readcharfun, Qget_file_char))
{
- if (end - p < MAX_MULTIBYTE_LENGTH)
+ /* This is the below "do" loop with changes:
+
+ Some calls to READCHAR and readbyte_from_file are
+ expanded inline with irrelevant branches including
+ MULE support pruned.
+
+ Instead of blocking and unblocking input around each
+ getc call, we block input at the start and unblock at
+ the end, and make the "normal" state in this loop to
+ have input being blocked. Calls to functions that
+ may signal errors are wrapped in unblock/block calls.
+
+ This keeps us from constantly fiddling with input
+ blocking in the common case of scanning additional
+ ASCII symbol name characters (other than backslash)
+ without interrupted reads.
+
+ This is done for performance reasons. */
+ block_input ();
+ do
{
- ptrdiff_t offset = p - read_buffer;
- grow_read_buffer ();
- p = read_buffer + offset;
- end = read_buffer + read_buffer_size;
- }
+ if (end - p < MAX_MULTIBYTE_LENGTH)
+ {
+ ptrdiff_t offset = p - read_buffer;
+ unblock_input ();
+ grow_read_buffer ();
+ block_input ();
+ p = read_buffer + offset;
+ end = read_buffer + read_buffer_size;
+ }
+
+ if (c == '\\')
+ {
+ unblock_input ();
+ c = READCHAR;
+ if (c == -1)
+ end_of_file_error ();
+ quoted = 1;
+ block_input ();
+ }
+
+ if (multibyte)
+ p += CHAR_STRING (c, (unsigned char *) p);
+ else
+ *p++ = c;
+ /* c = READCHAR; expanded below: */
+ readchar_count++;
+ if (unread_char >= 0)
+ {
+ c = unread_char;
+ unread_char = -1;
+ }
+ else
+ {
+ unsigned char buf[MAX_MULTIBYTE_LENGTH];
+ int i, len;
+
+ /* c = readbyte_from_file (-1, readcharfun); */
+ /* expands into: */
+ c = getc_unlocked (instream);
+
+ /* Interrupted reads have been observed while
+ reading over the network. */
+ while (c == EOF && ferror (instream) && errno == EINTR)
+ {
+ unblock_input ();
+ QUIT;
+ block_input ();
+ clearerr (instream);
+ c = getc_unlocked (instream);
+ }
- if (c == '\\')
+ if (c == EOF)
+ c = -1;
+
+ if (c < 0)
+ goto have_char_from_file;
+ if (ASCII_CHAR_P (c))
+ goto have_char_from_file;
+ i = 0;
+ buf[i++] = c;
+ len = BYTES_BY_CHAR_HEAD (c);
+ while (i < len)
+ {
+ unblock_input ();
+ c = readbyte_from_file (-1, readcharfun);
+ if (c < 0 || ! TRAILING_CODE_P (c))
+ {
+ while (--i > 1)
+ readbyte_from_file (buf[i], readcharfun);
+ c = BYTE8_TO_CHAR (buf[0]);
+ block_input ();
+ goto have_char_from_file;
+ }
+ buf[i++] = c;
+ }
+ c = STRING_CHAR (buf);
+ /* fall through */
+ have_char_from_file:
+ /* Input should be blocked at this point. */
+ ;
+ }
+ }
+ while (c > 040
+ && c != NO_BREAK_SPACE
+ && (c >= 0200
+ || strchr ("\"';()[]#`,", c) == NULL));
+ unblock_input ();
+ }
+ else
+ {
+ do
{
+ if (end - p < MAX_MULTIBYTE_LENGTH)
+ {
+ ptrdiff_t offset = p - read_buffer;
+ grow_read_buffer ();
+ p = read_buffer + offset;
+ end = read_buffer + read_buffer_size;
+ }
+
+ if (c == '\\')
+ {
+ c = READCHAR;
+ if (c == -1)
+ end_of_file_error ();
+ quoted = 1;
+ }
+
+ if (multibyte)
+ p += CHAR_STRING (c, (unsigned char *) p);
+ else
+ *p++ = c;
c = READCHAR;
- if (c == -1)
- end_of_file_error ();
- quoted = 1;
}
-
- if (multibyte)
- p += CHAR_STRING (c, (unsigned char *) p);
- else
- *p++ = c;
- c = READCHAR;
+ while (c > 040
+ && c != NO_BREAK_SPACE
+ && (c >= 0200
+ || strchr ("\"';()[]#`,", c) == NULL));
}
- while (c > 040
- && c != NO_BREAK_SPACE
- && (c >= 0200
- || strchr ("\"';()[]#`,", c) == NULL));
if (p == end)
{
- [Emacs-diffs] scratch/raeburn-startup f48e12c 06/17: Reduce nested calls during substitution., (continued)
- [Emacs-diffs] scratch/raeburn-startup f48e12c 06/17: Reduce nested calls during substitution., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup 702bcad 15/17: Don't memset storage we're about to fill anyway., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup c95f727 16/17: Dump defvars for special variables only., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup 8e7ec27 07/17: Use a hash table for seen_list, similar to read_objects_map., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup dcc4b55 04/17: Replace read_objects assoc list with two hash tables., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup 8f37b82 08/17: Stefan's patch to write out and load "dumped.elc"; Oct 31 version., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup 872c9f6 05/17: Don't generate excessive hash tables during reads., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup 44f3368 11/17: Force purification off when using dumped.elc., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup 2fa607a 10/17: Increase the obarray size., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup 6120138 12/17: Don't get into an error loop if dumped.elc isn't found., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup 913592c 14/17: Optimize reading of ASCII symbols from a .elc file.,
Ken Raeburn <=
- [Emacs-diffs] scratch/raeburn-startup 5c337b4 01/17: Use getc_unlocked., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup 6a7d996 17/17: Don't dump a copy of the obarray., Ken Raeburn, 2016/12/15
- [Emacs-diffs] scratch/raeburn-startup 4c8f07e 09/17: Increase gc-cons-threshold., Ken Raeburn, 2016/12/15