--------------------- PatchSet 2764 Date: 2001/08/15 23:54:36 Author: adri Branch: diskio Tag: (none) Log: Add the zero-copy-storeClientCopy - if a NULL is supplied, a pointer to an existing buffer is passed to the callback, rather than data being copied into a supplied buffer. This has come over from commloops and its the first step in improving the network/disk IO in the current codebase. commloops has working patches for the http client code to use this, but I haven't committed them yet. One of the requirements will being able to accept an arbitrarily-large buffer. This means something like storeRead() will be able to return a large (say, 64k) buffer containing the entire object. I'll probably end up using cbdata'ed buffers here. :-) Members: src/enums.h:1.22->1.22.2.1 src/mem.c:1.12->1.12.16.1 src/store_client.c:1.8->1.8.24.1 src/structs.h:1.38->1.38.2.1 Index: squid/src/enums.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/enums.h,v retrieving revision 1.22 retrieving revision 1.22.2.1 diff -u -r1.22 -r1.22.2.1 --- squid/src/enums.h 12 Aug 2001 15:20:28 -0000 1.22 +++ squid/src/enums.h 15 Aug 2001 23:54:36 -0000 1.22.2.1 @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.22 2001/08/12 15:20:28 squidadm Exp $ + * $Id: enums.h,v 1.22.2.1 2001/08/15 23:54:36 adri Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -606,6 +606,7 @@ MEM_RELIST, MEM_REQUEST_T, MEM_STMEM_BUF, + MEM_STMEM_TRANSITBUF, MEM_STOREENTRY, MEM_WORDLIST, #if !USE_DNSSERVERS Index: squid/src/mem.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/mem.c,v retrieving revision 1.12 retrieving revision 1.12.16.1 diff -u -r1.12 -r1.12.16.1 --- squid/src/mem.c 20 Apr 2001 21:35:33 -0000 1.12 +++ squid/src/mem.c 15 Aug 2001 23:54:36 -0000 1.12.16.1 @@ -1,6 +1,6 @@ /* - * $Id: mem.c,v 1.12 2001/04/20 21:35:33 squidadm Exp $ + * $Id: mem.c,v 1.12.16.1 2001/08/15 23:54:36 adri Exp $ * * DEBUG: section 13 High Level Memory Pool Management * AUTHOR: Harvest Derived @@ -233,6 +233,7 @@ Squid_MaxFD >> 3); memDataInit(MEM_STMEM_BUF, "Store Mem Buffer", SM_PAGE_SIZE, Config.memMaxSize / SM_PAGE_SIZE); + memDataInit(MEM_STMEM_TRANSITBUF, "Transit buffer", SM_PAGE_SIZE, 0); memDataInit(MEM_STOREENTRY, "StoreEntry", sizeof(StoreEntry), 0); memDataInit(MEM_WORDLIST, "wordlist", sizeof(wordlist), 0); memDataInit(MEM_CLIENT_INFO, "ClientInfo", sizeof(ClientInfo), 0); Index: squid/src/store_client.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store_client.c,v retrieving revision 1.8 retrieving revision 1.8.24.1 diff -u -r1.8 -r1.8.24.1 --- squid/src/store_client.c 14 Apr 2001 00:31:02 -0000 1.8 +++ squid/src/store_client.c 15 Aug 2001 23:54:36 -0000 1.8.24.1 @@ -1,6 +1,6 @@ /* - * $Id: store_client.c,v 1.8 2001/04/14 00:31:02 squidadm Exp $ + * $Id: store_client.c,v 1.8.24.1 2001/08/15 23:54:36 adri Exp $ * * DEBUG: section 20 Storage Manager Client-Side Interface * AUTHOR: Duane Wessels @@ -141,6 +141,8 @@ sc->flags.disk_io_pending = 0; sc->entry = e; sc->type = storeClientType(e); + sc->listp = 0; + sc->listofs = -1; if (sc->type == STORE_DISK_CLIENT) /* assert we'll be able to get the data we want */ /* maybe we should open swapin_fd here */ @@ -162,6 +164,12 @@ sc->copy_buf = NULL; if (cbdataValid(sc->callback_data)) callback(sc->callback_data, buf, sz); + + /* Free the memory where required */ + if (sc->flags.store_zerocopyswapin == 1) { + sc->flags.store_zerocopyswapin = 0; + memFree(buf, MEM_STMEM_TRANSITBUF); + } } static void @@ -206,6 +214,7 @@ sc->copy_buf = buf; sc->copy_size = size; sc->copy_offset = copy_offset; + storeClientCopy2(e, sc); } @@ -267,12 +276,17 @@ { MemObject *mem = e->mem_obj; size_t sz; + int offset, mp_ofs; + mem_node *mp = NULL; + + debug(33, 5) ("co: %d, seen: %d, hi: %d\n", sc->copy_offset, sc->seen_offset, mem->inmem_hi); if (storeClientNoMoreToSend(e, sc)) { /* There is no more to send! */ storeClientCallback(sc, 0); return; } + if (e->store_status == STORE_PENDING && sc->seen_offset >= mem->inmem_hi) { /* client has already seen this, wait for more */ debug(20, 3) ("storeClientCopy3: Waiting for more\n"); @@ -289,6 +303,7 @@ * is clientCacheHit) so that we can fall back to a cache miss * if needed. */ + if (STORE_DISK_CLIENT == sc->type && NULL == sc->swapin_sio) { debug(20, 3) ("storeClientCopy3: Need to open swap in file\n"); /* gotta open the swapin file */ @@ -314,10 +329,78 @@ } if (sc->copy_offset >= mem->inmem_lo && sc->copy_offset < mem->inmem_hi) { /* What the client wants is in memory */ - debug(20, 3) ("storeClientCopy3: Copying from memory\n"); - sz = stmemCopy(&mem->data_hdr, - sc->copy_offset, sc->copy_buf, sc->copy_size); - storeClientCallback(sc, sz); + /* + * We are now throwing data to clients in SM_PAGE_SIZE chunks, following + * the mem_node linked list just like src/store_swapout.c does. We send + * data to a client when we have at least a page to send, and we only + * send partial pages when we have the entire object in memory. We then + * throw the buffer to the callback, and let the callback routine use + * the buffer directly rather than copy and waste memory. Yes, evil, + * but thats life, right? + */ + /* Fudge to figure out whether we're doing the old or new style call */ + if (sc->copy_buf != NULL) { + /* Old style */ + debug(20, 3) ("storeClientCopy3: Copying normal from memory\n"); + sz = stmemCopy(&mem->data_hdr, + sc->copy_offset, sc->copy_buf, sc->copy_size); + storeClientCallback(sc, sz); + return; + } + + /* New-style */ + /* XXX Traverse the membuf list, find the memnode and offset, + * and use that buffer. We still end up walking the list :( .. + * its a temporary hack. When the code works, I'd like to do this: + * + * - if we don't have a 'hint' mem_node *, we traverse the list + * and look for it + * - if we do have a hint mem_node *, we use it as the basis + * for figuring out the next mem_node to look at, and if we + * can't figure it out, just fallback to the route search. + */ + + /* Whats the offset? :-) */ + offset = sc->copy_offset; + + /* If we can use this memnode, then damn well use it! */ + if (sc->listp && sc->listofs >= offset) { + mp = sc->listp; + mp_ofs = sc->listofs; + } else { + mp = mem->data_hdr.head; + mp_ofs = mem->inmem_lo; + } + assert(mp); + /* XXX THIS SHOULD BE IN STMEM.C!!!! */ + while ((mp_ofs + mp->len - 1) < offset) { + mp_ofs += mp->len; + if (!mp->next) { + /* No match */ + mp = NULL; + break; + } + assert(mp->next); + mp = mp->next; + } + /* Keep the hint .. */ + sc->listp = mp; + sc->listofs = mp_ofs; + + /* + * Ok, we have mp_ofs with the offset of this mem_node, and mp + * which is the current memnode. The offset inside the memnode + * we need to be is offset - mp_ofs, and the length of the data + * we are handing off is mp->len - sz. + */ + sz = offset - mp_ofs; + + /* Call the callback with the buffer */ + sc->flags.disk_io_pending = 0; + debug(20, 5) ("storeClientCopy2: copy_offset = %d, seen_offset = %d\n", sc->copy_offset, sc->seen_offset); + debug(20, 5) ("storeClientCopy2: copying %d bytes of data from offset %d in the membuf of size %d\n", mp->len - sz, sz, mp->len); + sc->copy_buf = mp->data + sz; + storeClientCallback(sc, mp->len - sz); return; } /* What the client wants is not in memory. Schedule a disk read */ @@ -331,6 +414,16 @@ storeClientFileRead(store_client * sc) { MemObject *mem = sc->entry->mem_obj; + + if (sc->copy_buf == NULL) { + /* XXX SHOULD BE SM_PAGE_SIZE! */ + sc->copy_buf = memAllocate(MEM_STMEM_TRANSITBUF); + sc->copy_size = SM_PAGE_SIZE; + sc->flags.store_zerocopyswapin = 1; + } else { + sc->flags.store_zerocopyswapin = 0; + } + assert(sc->callback != NULL); assert(!sc->flags.disk_io_pending); sc->flags.disk_io_pending = 1; Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.38 retrieving revision 1.38.2.1 diff -u -r1.38 -r1.38.2.1 --- squid/src/structs.h 12 Aug 2001 15:20:28 -0000 1.38 +++ squid/src/structs.h 15 Aug 2001 23:54:36 -0000 1.38.2.1 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.38 2001/08/12 15:20:28 squidadm Exp $ + * $Id: structs.h,v 1.38.2.1 2001/08/15 23:54:36 adri Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -1401,11 +1401,16 @@ unsigned int disk_io_pending:1; unsigned int store_copying:1; unsigned int copy_event_pending:1; + unsigned int store_zerocopyswapin:1; } flags; #if DELAY_POOLS delay_id delay_id; #endif dlink_node node; + + /* Stuff for list hinting */ + mem_node *listp; /* next list mem_node */ + int listofs; /* offset of this mem_node */ };