added madvise, smaller mmap()ed windows and local-buffering

(step 1 and 2 of the optimizations)


git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-merge-1.4.x@796 152afb58-edef-0310-8abb-c4023f1b3aa9
svn/tags/lighttpd-1.4.7
Jan Kneschke 17 years ago
parent c87a000c13
commit 03452de486
  1. 96
      src/network_writev.c

@ -19,6 +19,7 @@
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
#include <assert.h>
#include "network.h"
#include "fdevent.h"
@ -46,6 +47,10 @@
# endif
#endif
#if 0
#define LOCAL_BUFFERING 1
#endif
int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
chunk *c;
size_t chunks_written = 0;
@ -148,17 +153,23 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq
case FILE_CHUNK: {
ssize_t r;
off_t offset;
size_t toSend;
off_t toSend;
stat_cache_entry *sce = NULL;
#define KByte * 1024
#define MByte * 1024 KByte
#define GByte * 1024 MByte
const off_t we_want_to_mmap = 512 KByte;
off_t we_want_to_send = c->file.length - c->offset;
char *start = NULL;
if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
log_error_write(srv, __FILE__, __LINE__, "sb",
strerror(errno), c->file.name);
return -1;
}
offset = c->file.offset + c->offset;
toSend = c->file.length - c->offset;
offset = c->file.start + c->offset;
if (offset > sce->st.st_size) {
log_error_write(srv, __FILE__, __LINE__, "sb",
@ -167,13 +178,11 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq
return -1;
}
if (c->file.mmap.start == MAP_FAILED) {
if (-1 == c->file.fd && /* open the file if not already open */
-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
return -1;
}
/* mmap the buffer
* - first mmap
* - new mmap as the we are at the end of the last one */
if (c->file.mmap.start == MAP_FAILED ||
offset == c->file.mmap.offset + c->file.mmap.length) {
/* Optimizations for the future:
*
@ -195,37 +204,64 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq
* 2. use a internal read-ahead buffer in the chunk-structure
* 3. use non-blocking IO for file-transfers
* */
if (MAP_FAILED == (c->file.mmap.start = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
/* all mmap()ed areas are 16Mbyte expect the last which might be smaller */
size_t to_mmap = (we_want_to_send < we_want_to_mmap) ? we_want_to_send : we_want_to_mmap;
/* this is a remap, move the mmap-offset */
if (c->file.mmap.start != MAP_FAILED) {
munmap(c->file.mmap.start, c->file.mmap.length);
c->file.mmap.offset += we_want_to_mmap;
} else {
/* in case the range-offset is after the first mmap()ed area we skip the area */
c->file.mmap.offset = 0;
while (c->file.mmap.offset + we_want_to_mmap < c->file.start) {
c->file.mmap.offset += we_want_to_mmap;
}
}
if (-1 == c->file.fd) { /* open the file if not already open */
if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
return -1;
}
#ifdef FD_CLOEXEC
fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
#endif
}
if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
/* close it here, otherwise we'd have to set FD_CLOEXEC */
close(c->file.fd);
c->file.fd = -1;
log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
strerror(errno), c->file.name, c->file.fd);
log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
strerror(errno), c->file.name, c->file.fd);
return -1;
}
#ifdef USE_MADVISE
/* we should use a sliding window here and only advise on the mmaped range and not
* on the full file (waiting for adaptive mem-mapping) */
if (0 != madvise(c->file.mmap.start, sce->st.st_size, MADV_SEQUENTIAL)) {
log_error_write(srv, __FILE__, __LINE__, "ssbd", "madvise failed: ",
strerror(errno), c->file.name, c->file.fd);
return -1;
c->file.mmap.length = to_mmap;
#ifdef LOCAL_BUFFERING
buffer_copy_string_len(c->mem, c->file.mmap.start, c->file.mmap.length);
#else
if (0 != madvise(c->file.mmap.start, c->file.mmap.length, MADV_WILLNEED)) {
log_error_write(srv, __FILE__, __LINE__, "ssbd", "madvise failed:",
strerror(errno), c->file.name, c->file.fd);
}
#endif
close(c->file.fd);
c->file.fd = -1;
c->file.mmap.length = sce->st.st_size;
/* chunk_reset() or chunk_free() will cleanup for us */
}
toSend = c->file.mmap.length - (offset - c->file.mmap.offset);
#ifdef LOCAL_BUFFERING
start = c->mem->ptr;
#else
start = c->file.mmap.start;
#endif
if ((r = write(fd, c->file.mmap.start + offset, toSend)) < 0) {
if ((r = write(fd, start + (offset - c->file.mmap.offset), toSend)) < 0) {
switch (errno) {
case EAGAIN:
case EINTR:

Loading…
Cancel
Save