reduce overhead for simple port char/byte reads/writes

Cut the overhead by 30% or so by making the fast path need less
cooperation with the GC.
This commit is contained in:
Matthew Flatt 2016-05-09 09:11:47 -06:00
parent 6c9a4cb470
commit 8e7792d85a
2 changed files with 135 additions and 21 deletions

View File

@ -3312,8 +3312,7 @@ static MZ_INLINE intptr_t get_one_byte(GC_CAN_IGNORE const char *who,
return get_one_byte_slow(who, port, buffer, 0, 0); return get_one_byte_slow(who, port, buffer, 0, 0);
} }
int int scheme_getc(Scheme_Object *port)
scheme_getc(Scheme_Object *port)
{ {
char s[MAX_UTF8_CHAR_BYTES]; char s[MAX_UTF8_CHAR_BYTES];
unsigned int r[1]; unsigned int r[1];
@ -3362,7 +3361,7 @@ scheme_getc(Scheme_Object *port)
} }
int int
scheme_get_byte(Scheme_Object *port) scheme_get_byte(Scheme_Object *port) XFORM_ASSERT_NO_CONVERSION
{ {
char s[1]; char s[1];
int v; int v;
@ -4194,10 +4193,10 @@ int scheme_close_should_force_port_closed()
/****************************** main output writer ******************************/ /****************************** main output writer ******************************/
intptr_t static intptr_t
scheme_put_byte_string(const char *who, Scheme_Object *port, put_byte_string_slow(const char *who, Scheme_Object *port,
const char *str, intptr_t d, intptr_t len, const char *str, intptr_t d, intptr_t len,
int rarely_block) int rarely_block)
{ {
/* Unlike the main reader, the main writer is simple. It doesn't /* Unlike the main reader, the main writer is simple. It doesn't
have to deal with peeks and specials, so it's a thin wrapper on have to deal with peeks and specials, so it's a thin wrapper on
@ -4262,6 +4261,32 @@ scheme_put_byte_string(const char *who, Scheme_Object *port,
return oout; return oout;
} }
intptr_t
scheme_put_byte_string(GC_CAN_IGNORE const char *who, Scheme_Object *port,
GC_CAN_IGNORE const char *str, intptr_t d, intptr_t len,
int rarely_block)
{
intptr_t out;
if (SCHEME_OUTPORTP(port)
&& !((Scheme_Output_Port *)port)->closed
&& (rarely_block != -1)
&& (len == 1)
&& !((Scheme_Output_Port *)port)->p.count_lines) {
Scheme_Output_Port *op = (Scheme_Output_Port *)port;
Scheme_Write_String_Fun ws;
ws = op->write_string_fun;
out = ws(op, str, d, 1, rarely_block, 0);
if (out) {
op->p.position += out;
return out;
} else if (rarely_block)
return 0;
}
return put_byte_string_slow(who, port, str, d, len, rarely_block);
}
void scheme_write_byte_string(const char *str, intptr_t len, Scheme_Object *port) void scheme_write_byte_string(const char *str, intptr_t len, Scheme_Object *port)
{ {
(void)scheme_put_byte_string("write-string", port, str, 0, len, 0); (void)scheme_put_byte_string("write-string", port, str, 0, len, 0);
@ -6923,9 +6948,10 @@ static intptr_t fd_get_string_slow(Scheme_Input_Port *port,
} }
static intptr_t fd_get_string(Scheme_Input_Port *port, static intptr_t fd_get_string(Scheme_Input_Port *port,
char *buffer, intptr_t offset, intptr_t size, char *buffer, intptr_t offset, intptr_t size,
int nonblock, int nonblock,
Scheme_Object *unless) Scheme_Object *unless)
XFORM_ASSERT_NO_CONVERSION
{ {
Scheme_FD *fip; Scheme_FD *fip;
intptr_t bc; intptr_t bc;
@ -8206,9 +8232,9 @@ static intptr_t flush_fd(Scheme_Output_Port *op,
} }
static intptr_t static intptr_t
fd_write_string(Scheme_Output_Port *port, fd_write_string_slow(Scheme_Output_Port *port,
const char *str, intptr_t d, intptr_t len, const char *str, intptr_t d, intptr_t len,
int rarely_block, int enable_break) int rarely_block, int enable_break)
{ {
/* Note: !flush => !rarely_block, !len => flush */ /* Note: !flush => !rarely_block, !len => flush */
@ -8280,6 +8306,30 @@ fd_write_string(Scheme_Output_Port *port,
return len; return len;
} }
static intptr_t
fd_write_string(Scheme_Output_Port *port,
const char *str, intptr_t d, intptr_t len,
int rarely_block, int enable_break)
XFORM_ASSERT_NO_CONVERSION
{
Scheme_FD *fop;
intptr_t l;
int flush = (!len || rarely_block);
fop = (Scheme_FD *)port->port_data;
if (!flush && !fop->flushing && (fop->flush != MZ_FLUSH_ALWAYS)) {
l = MZPORT_FD_BUFFSIZE - fop->bufcount;
if (len <= l) {
memcpy(fop->buffer + fop->bufcount, str + d, len);
fop->bufcount += len;
return len;
}
}
return fd_write_string_slow(port, str, d, len, rarely_block, enable_break);
}
static void static void
fd_close_output(Scheme_Output_Port *port) fd_close_output(Scheme_Output_Port *port)
{ {

View File

@ -3112,9 +3112,24 @@ do_read_char(char *name, int argc, Scheme_Object *argv[], int peek, int spec, in
return _scheme_make_char(ch); return _scheme_make_char(ch);
} }
static Scheme_Object * static Scheme_Object *read_char_fast(Scheme_Object *port) XFORM_ASSERT_NO_CONVERSION
read_char (int argc, Scheme_Object *argv[])
{ {
int ch;
ch = scheme_getc(port);
if (ch == EOF)
return scheme_eof;
else
return _scheme_make_char(ch);
}
static Scheme_Object *
read_char (int argc, Scheme_Object *argv[]) XFORM_ASSERT_NO_CONVERSION
{
if (argc && SCHEME_INPUT_PORTP(argv[0]))
return read_char_fast(argv[0]);
return do_read_char("read-char", argc, argv, 0, 0, 0); return do_read_char("read-char", argc, argv, 0, 0, 0);
} }
@ -3136,9 +3151,24 @@ peek_char_spec (int argc, Scheme_Object *argv[])
return do_read_char("peek-char-or-special", argc, argv, 1, 1, 0); return do_read_char("peek-char-or-special", argc, argv, 1, 1, 0);
} }
static Scheme_Object * static Scheme_Object *read_byte_fast(Scheme_Object *port) XFORM_ASSERT_NO_CONVERSION
read_byte (int argc, Scheme_Object *argv[])
{ {
int ch;
ch = scheme_get_byte(port);
if (ch == EOF)
return scheme_eof;
else
return scheme_make_integer(ch);
}
static Scheme_Object *
read_byte (int argc, Scheme_Object *argv[]) XFORM_ASSERT_NO_CONVERSION
{
if (argc && SCHEME_INPUT_PORTP(argv[0]))
return read_byte_fast(argv[0]);
return do_read_char("read-byte", argc, argv, 0, 0, 1); return do_read_char("read-byte", argc, argv, 0, 0, 1);
} }
@ -4107,13 +4137,13 @@ newline (int argc, Scheme_Object *argv[])
} }
static Scheme_Object * static Scheme_Object *
write_byte (int argc, Scheme_Object *argv[]) write_byte_slow (int argc, Scheme_Object *argv[])
{ {
Scheme_Object *port; Scheme_Object *port;
int v; int v;
unsigned char buffer[1]; unsigned char buffer[1];
if (argc && !SCHEME_INTP(argv[0])) if (!SCHEME_INTP(argv[0]))
scheme_wrong_contract("write-byte", "byte?", 0, argc, argv); scheme_wrong_contract("write-byte", "byte?", 0, argc, argv);
v = SCHEME_INT_VAL(argv[0]); v = SCHEME_INT_VAL(argv[0]);
if ((v < 0) || (v > 255)) if ((v < 0) || (v > 255))
@ -4136,14 +4166,31 @@ write_byte (int argc, Scheme_Object *argv[])
} }
static Scheme_Object * static Scheme_Object *
write_char (int argc, Scheme_Object *argv[]) write_byte (int argc, GC_CAN_IGNORE Scheme_Object *argv[]) XFORM_ASSERT_NO_CONVERSION
{
if (SCHEME_INTP(argv[0])
&& (SCHEME_INT_VAL(argv[0]) >= 0)
&& (SCHEME_INT_VAL(argv[0]) <= 255)
&& SCHEME_OUTPUT_PORTP(argv[1])) {
char buffer[1];
buffer[0] = SCHEME_INT_VAL(argv[0]);
scheme_put_byte_string("write-byte", argv[1],
buffer, 0, 1,
0);
return scheme_void;
} else
return write_byte_slow(argc, argv);
}
static Scheme_Object *
write_char_slow (int argc, Scheme_Object *argv[])
{ {
Scheme_Object *port; Scheme_Object *port;
unsigned char buffer[MAX_UTF8_CHAR_BYTES]; unsigned char buffer[MAX_UTF8_CHAR_BYTES];
unsigned int ubuffer[1]; unsigned int ubuffer[1];
int len; int len;
if (argc && !SCHEME_CHARP(argv[0])) if (!SCHEME_CHARP(argv[0]))
scheme_wrong_contract("write-char", "char?", 0, argc, argv); scheme_wrong_contract("write-char", "char?", 0, argc, argv);
if (argc > 1) { if (argc > 1) {
if (!SCHEME_OUTPUT_PORTP(argv[1])) if (!SCHEME_OUTPUT_PORTP(argv[1]))
@ -4162,6 +4209,23 @@ write_char (int argc, Scheme_Object *argv[])
return scheme_void; return scheme_void;
} }
static Scheme_Object *
write_char (int argc, GC_CAN_IGNORE Scheme_Object *argv[]) XFORM_ASSERT_NO_CONVERSION
{
if (argc
&& SCHEME_CHARP(argv[0])
&& (SCHEME_CHAR_VAL(argv[0]) < 128)
&& SCHEME_OUTPUT_PORTP(argv[1])) {
char buffer[1];
buffer[0] = SCHEME_CHAR_VAL(argv[0]);
scheme_put_byte_string("write-char", argv[1],
buffer, 0, 1,
0);
return scheme_void;
} else
return write_char_slow(argc, argv);
}
static Scheme_Object *port_read_handler(int argc, Scheme_Object *argv[]) static Scheme_Object *port_read_handler(int argc, Scheme_Object *argv[])
{ {
Scheme_Input_Port *ip; Scheme_Input_Port *ip;