Browse Source

[core] network_write optimizations

more shared code, better asm
master
Glenn Strauss 6 months ago
parent
commit
c5dd8905e1
  1. 169
      src/network_write.c

169
src/network_write.c

@ -67,6 +67,7 @@
#endif
__attribute_cold__
static int network_write_error(int fd, log_error_st *errh) {
#if defined(__WIN32)
int lastError = WSAGetLastError();
@ -88,7 +89,7 @@ static int network_write_error(int fd, log_error_st *errh) {
case EINTR:
return -3;
case EPIPE:
case ECONNRESET:
case ECONNRESET:
return -2;
default:
log_perror(errh,__FILE__,__LINE__,"write failed: %d",fd);
@ -97,6 +98,13 @@ static int network_write_error(int fd, log_error_st *errh) {
#endif /* __WIN32 */
}
__attribute_cold__
static int network_remove_finished_chunks(chunkqueue * const cq, const off_t len) {
force_assert(len >= 0);
chunkqueue_remove_finished_chunks(cq);
return 0;
}
inline
static ssize_t network_write_data_len(int fd, const char *data, off_t len) {
#if defined(__WIN32)
@ -106,33 +114,31 @@ static ssize_t network_write_data_len(int fd, const char *data, off_t len) {
#endif /* __WIN32 */
}
static int network_write_accounting(const int fd, chunkqueue * const cq, off_t * const p_max_bytes, log_error_st * const errh, const ssize_t wr, const off_t toSend) {
if (wr >= 0) {
*p_max_bytes -= wr;/*(toSend > 0 if we reach this func)*/
const int rc = (wr == toSend && *p_max_bytes > 0) ? 0 : -3;
chunkqueue_mark_written(cq, wr);
return rc;
}
else
return network_write_error(fd, errh);
}
/* write next chunk(s); finished chunks are removed afterwards after successful writes.
* return values: similar as backends (0 success, -1 error, -2 remote close, -3 try again later (EINTR/EAGAIN)) */
/* next chunk must be MEM_CHUNK. use write()/send() */
static int network_write_mem_chunk(int fd, chunkqueue *cq, off_t *p_max_bytes, log_error_st *errh) {
static int network_write_mem_chunk(const int fd, chunkqueue * const cq, off_t * const p_max_bytes, log_error_st * const errh) {
chunk* const c = cq->first;
ssize_t wr;
off_t c_len = (off_t)buffer_string_length(c->mem);
force_assert(c->offset >= 0 && c->offset <= c_len);
c_len -= c->offset;
off_t c_len = (off_t)buffer_string_length(c->mem) - c->offset;
if (c_len > *p_max_bytes) c_len = *p_max_bytes;
if (c_len <= 0) return network_remove_finished_chunks(cq, c_len);
if (0 == c_len) {
chunkqueue_remove_finished_chunks(cq);
return 0;
}
wr = network_write_data_len(fd, c->mem->ptr + c->offset, c_len);
if (wr >= 0) {
*p_max_bytes -= wr;
chunkqueue_mark_written(cq, wr);
return (wr > 0 && wr == c_len) ? 0 : -3;
} else {
return network_write_error(fd, errh);
}
ssize_t wr = network_write_data_len(fd, c->mem->ptr + c->offset, c_len);
return network_write_accounting(fd, cq, p_max_bytes, errh, wr, c_len);
}
@ -140,22 +146,15 @@ static int network_write_mem_chunk(int fd, chunkqueue *cq, off_t *p_max_bytes, l
#if !defined(NETWORK_WRITE_USE_MMAP)
static int network_write_file_chunk_no_mmap(int fd, chunkqueue *cq, off_t *p_max_bytes, log_error_st *errh) {
static int network_write_file_chunk_no_mmap(const int fd, chunkqueue * const cq, off_t * const p_max_bytes, log_error_st * const errh) {
chunk* const c = cq->first;
off_t offset, toSend;
ssize_t wr;
char buf[16384]; /* max read 16kb in one step */
force_assert(c->offset >= 0 && c->offset <= c->file.length);
offset = c->offset;
toSend = c->file.length - c->offset;
if (toSend > *p_max_bytes) toSend = *p_max_bytes;
if (0 == toSend) {
chunkqueue_remove_finished_chunks(cq);
return 0;
}
if (toSend <= 0) return network_remove_finished_chunks(cq, toSend);
if (c->file.fd < 0 && 0 != chunkqueue_open_file_chunk(cq, errh)) return -1;
@ -170,14 +169,8 @@ static int network_write_file_chunk_no_mmap(int fd, chunkqueue *cq, off_t *p_max
return -1;
}
wr = network_write_data_len(fd, buf, toSend);
if (wr >= 0) {
*p_max_bytes -= wr;
chunkqueue_mark_written(cq, wr);
return (wr > 0 && wr == toSend) ? 0 : -3;
} else {
return network_write_error(fd, errh);
}
ssize_t wr = network_write_data_len(fd, buf, toSend);
return network_write_accounting(fd, cq, p_max_bytes, errh, wr, toSend);
}
#endif
@ -214,24 +207,17 @@ static void sigbus_handler(int sig) {
}
/* next chunk must be FILE_CHUNK. send mmap()ed file with write() */
static int network_write_file_chunk_mmap(int fd, chunkqueue *cq, off_t *p_max_bytes, log_error_st *errh) {
static int network_write_file_chunk_mmap(const int fd, chunkqueue * const cq, off_t * const p_max_bytes, log_error_st * const errh) {
chunk* const c = cq->first;
off_t offset, toSend, file_end;
ssize_t wr;
size_t mmap_offset, mmap_avail;
const char *data;
force_assert(c->offset >= 0 && c->offset <= c->file.length);
file_end = c->file.length; /*file end offset in this chunk*/
offset = c->offset;
toSend = c->file.length - c->offset;
if (toSend > *p_max_bytes) toSend = *p_max_bytes;
file_end = c->file.length; /*file end offset in this chunk*/
if (0 == toSend) {
chunkqueue_remove_finished_chunks(cq);
return 0;
}
if (toSend <= 0) return network_remove_finished_chunks(cq, toSend);
if (c->file.fd < 0 && 0 != chunkqueue_open_file_chunk(cq, errh)) return -1;
@ -309,8 +295,9 @@ static int network_write_file_chunk_mmap(int fd, chunkqueue *cq, off_t *p_max_by
signal(SIGBUS, sigbus_handler);
sigbus_jmp_valid = 1;
wr = network_write_data_len(fd, data, toSend);
ssize_t wr = network_write_data_len(fd, data, toSend);
sigbus_jmp_valid = 0;
return network_write_accounting(fd, cq, p_max_bytes, errh, wr, toSend);
} else {
sigbus_jmp_valid = 0;
@ -322,13 +309,6 @@ static int network_write_file_chunk_mmap(int fd, chunkqueue *cq, off_t *p_max_by
return -1;
}
if (wr >= 0) {
*p_max_bytes -= wr;
chunkqueue_mark_written(cq, wr);
return (wr > 0 && wr == toSend) ? 0 : -3;
} else {
return network_write_error(fd, errh);
}
}
#endif /* NETWORK_WRITE_USE_MMAP */
@ -366,55 +346,28 @@ static int network_write_file_chunk_mmap(int fd, chunkqueue *cq, off_t *p_max_by
#endif
/* next chunk must be MEM_CHUNK. send multiple mem chunks using writev() */
static int network_writev_mem_chunks(int fd, chunkqueue *cq, off_t *p_max_bytes, log_error_st *errh) {
struct iovec chunks[MAX_CHUNKS];
static int network_writev_mem_chunks(const int fd, chunkqueue * const cq, off_t * const p_max_bytes, log_error_st * const errh) {
size_t num_chunks = 0;
off_t max_bytes = *p_max_bytes;
off_t toSend = 0;
ssize_t wr;
struct iovec chunks[MAX_CHUNKS];
for (const chunk *c = cq->first;
NULL != c && MEM_CHUNK == c->type
&& num_chunks < MAX_CHUNKS && toSend < max_bytes;
c = c->next) {
size_t c_len = buffer_string_length(c->mem);
force_assert(c->offset >= 0 && c->offset <= (off_t)c_len);
c_len -= c->offset;
for (const chunk *c = cq->first; c && MEM_CHUNK == c->type; c = c->next) {
const off_t c_len = (off_t)buffer_string_length(c->mem) - c->offset;
if (c_len > 0) {
toSend += c_len;
chunks[num_chunks].iov_base = c->mem->ptr + c->offset;
chunks[num_chunks].iov_len = c_len;
chunks[num_chunks].iov_len = (size_t)c_len;
++num_chunks;
if (++num_chunks == MAX_CHUNKS || toSend >= *p_max_bytes) break;
}
else if (c_len < 0) /*(should not happen; trigger assert)*/
return network_remove_finished_chunks(cq, c_len);
}
if (0 == num_chunks) return network_remove_finished_chunks(cq, 0);
if (0 == num_chunks) {
chunkqueue_remove_finished_chunks(cq);
return 0;
}
wr = writev(fd, chunks, num_chunks);
if (wr < 0) switch (errno) {
case EAGAIN:
case EINTR:
break;
case EPIPE:
case ECONNRESET:
return -2;
default:
log_perror(errh, __FILE__, __LINE__, "writev failed: %d", fd);
return -1;
}
if (wr >= 0) {
*p_max_bytes -= wr;
chunkqueue_mark_written(cq, wr);
}
return (wr > 0 && wr == toSend) ? 0 : -3;
ssize_t wr = writev(fd, chunks, num_chunks);
return network_write_accounting(fd, cq, p_max_bytes, errh, wr, toSend);
}
#endif /* NETWORK_WRITE_USE_WRITEV */
@ -434,23 +387,17 @@ static int network_writev_mem_chunks(int fd, chunkqueue *cq, off_t *p_max_bytes,
#include <sys/uio.h>
#endif
static int network_write_file_chunk_sendfile(int fd, chunkqueue *cq, off_t *p_max_bytes, log_error_st *errh) {
static int network_write_file_chunk_sendfile(const int fd, chunkqueue * const cq, off_t * const p_max_bytes, log_error_st * const errh) {
chunk * const c = cq->first;
ssize_t wr;
off_t offset;
off_t toSend;
off_t written = 0;
force_assert(c->offset >= 0 && c->offset <= c->file.length);
offset = c->offset;
toSend = c->file.length - c->offset;
if (toSend > *p_max_bytes) toSend = *p_max_bytes;
if (0 == toSend) {
chunkqueue_remove_finished_chunks(cq);
return 0;
}
if (toSend <= 0) return network_remove_finished_chunks(cq, toSend);
if (c->file.fd < 0 && 0 != chunkqueue_open_file_chunk(cq, errh)) return -1;
@ -529,6 +476,7 @@ static int network_write_file_chunk_sendfile(int fd, chunkqueue *cq, off_t *p_ma
if (written > 0) {
chunkqueue_mark_written(cq, written);
*p_max_bytes -= written;
if (__builtin_expect( (*p_max_bytes <= 0), 0)) return -3;
}
else if (0 == wr) { /*(-1 != wr && 0 == written)*/
log_error(errh, __FILE__, __LINE__,
@ -550,8 +498,8 @@ static int network_write_file_chunk_sendfile(int fd, chunkqueue *cq, off_t *p_ma
* -2 : remote close
*/
static int network_write_chunkqueue_write(int fd, chunkqueue *cq, off_t max_bytes, log_error_st *errh) {
while (max_bytes > 0 && NULL != cq->first) {
static int network_write_chunkqueue_write(const int fd, chunkqueue * const cq, off_t max_bytes, log_error_st * const errh) {
while (NULL != cq->first) {
int rc = -1;
switch (cq->first->type) {
@ -567,16 +515,15 @@ static int network_write_chunkqueue_write(int fd, chunkqueue *cq, off_t max_byte
break;
}
if (-3 == rc) return 0;
if (0 != rc) return rc;
if (__builtin_expect( (0 != rc), 0)) return (-3 == rc) ? 0 : rc;
}
return 0;
}
#if defined(NETWORK_WRITE_USE_WRITEV)
static int network_write_chunkqueue_writev(int fd, chunkqueue *cq, off_t max_bytes, log_error_st *errh) {
while (max_bytes > 0 && NULL != cq->first) {
static int network_write_chunkqueue_writev(const int fd, chunkqueue * const cq, off_t max_bytes, log_error_st * const errh) {
while (NULL != cq->first) {
int rc = -1;
switch (cq->first->type) {
@ -596,8 +543,7 @@ static int network_write_chunkqueue_writev(int fd, chunkqueue *cq, off_t max_byt
break;
}
if (-3 == rc) return 0;
if (0 != rc) return rc;
if (__builtin_expect( (0 != rc), 0)) return (-3 == rc) ? 0 : rc;
}
return 0;
@ -605,8 +551,8 @@ static int network_write_chunkqueue_writev(int fd, chunkqueue *cq, off_t max_byt
#endif
#if defined(NETWORK_WRITE_USE_SENDFILE)
static int network_write_chunkqueue_sendfile(int fd, chunkqueue *cq, off_t max_bytes, log_error_st *errh) {
while (max_bytes > 0 && NULL != cq->first) {
static int network_write_chunkqueue_sendfile(const int fd, chunkqueue * const cq, off_t max_bytes, log_error_st * const errh) {
while (NULL != cq->first) {
int rc = -1;
switch (cq->first->type) {
@ -628,8 +574,7 @@ static int network_write_chunkqueue_sendfile(int fd, chunkqueue *cq, off_t max_b
break;
}
if (-3 == rc) return 0;
if (0 != rc) return rc;
if (__builtin_expect( (0 != rc), 0)) return (-3 == rc) ? 0 : rc;
}
return 0;

Loading…
Cancel
Save