You are viewing a plain text version of this content. The canonical link for it is here.
Posted to apache-bugdb@apache.org by Takahiro Ishio <be...@bekkoame.ne.jp> on 2001/10/19 04:51:50 UTC

os-windows/8580: performance boost up on Windows

>Number:         8580
>Category:       os-windows
>Synopsis:       performance boost up on Windows
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    apache
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   apache
>Arrival-Date:   Thu Oct 18 20:00:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     bero@bekkoame.ne.jp
>Release:        1.3.22
>Organization:
apache
>Environment:
Windows 2000
>Description:
http://www.bekkoame.ne.jp/~bero/apache-mmap-en.html

Apache developer says "Warning: Apache on NT has not yet been optimized for performance. Apache still performs best, and is most reliable on Unix platforms. "
On Unix, apache use "mmap" function to read static contents.
I implement same functionality on Windows, then it is very high performance max 100 times.

BENCHMARK

/ and /index.html.en are default page of Apache distribution (1456 byte)
/webbench.jpg is 108026 byte

under Windows 2000 SP2,NTFS,Celeron 700,128MB memory

ab -n 100 c 10 (100 request 10 concurrent)

	/	/index.html.en	/webbench.jpg
normal	38.75	199.48		 487.60 (Kbyte/sec)
mmap	37.98	200.48		5152.49
cygwin	24.24	140.89		3824.25

ab -n 10 (10 requests 1 concurrent)

	/	/index.html.en	/webbench.jpg
normal	42.97	114.87		  49.19
mmap	41.92	107.69		1689.17
cygwin	24.30	 82.29		1439.91
>How-To-Repeat:

>Fix:
diff -u -r -N apache_1.3.22/src/ApacheCore.mak apache_1.3.22.mmap/src/ApacheCore.mak
--- apache_1.3.22/src/ApacheCore.mak	Thu Oct  4 12:55:22 2001
+++ apache_1.3.22.mmap/src/ApacheCore.mak	Fri Oct 19 17:42:50 2001
@@ -88,6 +88,7 @@
 	-@erase "$(INTDIR)\modules.obj"
 	-@erase "$(INTDIR)\multithread.obj"
 	-@erase "$(INTDIR)\readdir.obj"
+	-@erase "$(INTDIR)\mmap.obj"
 	-@erase "$(INTDIR)\registry.obj"
 	-@erase "$(INTDIR)\rfc1413.obj"
 	-@erase "$(INTDIR)\service.obj"
@@ -190,6 +191,7 @@
 	"$(INTDIR)\modules.obj" \
 	"$(INTDIR)\multithread.obj" \
 	"$(INTDIR)\readdir.obj" \
+	"$(INTDIR)\mmap.obj" \
 	"$(INTDIR)\registry.obj" \
 	"$(INTDIR)\rfc1413.obj" \
 	"$(INTDIR)\service.obj" \
@@ -269,6 +271,7 @@
 	-@erase "$(INTDIR)\modules.obj"
 	-@erase "$(INTDIR)\multithread.obj"
 	-@erase "$(INTDIR)\readdir.obj"
+	-@erase "$(INTDIR)\mmap.obj"
 	-@erase "$(INTDIR)\registry.obj"
 	-@erase "$(INTDIR)\rfc1413.obj"
 	-@erase "$(INTDIR)\service.obj"
@@ -372,6 +375,7 @@
 	"$(INTDIR)\modules.obj" \
 	"$(INTDIR)\multithread.obj" \
 	"$(INTDIR)\readdir.obj" \
+	"$(INTDIR)\mmap.obj" \
 	"$(INTDIR)\registry.obj" \
 	"$(INTDIR)\rfc1413.obj" \
 	"$(INTDIR)\service.obj" \
@@ -1274,6 +1278,15 @@
 	
 
 "$(INTDIR)\readdir.obj" : $(SOURCE) $(DEP_CPP_READD) "$(INTDIR)"
+	$(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\os\win32\mmap.c
+DEP_CPP_MMAP=\
+	".\os\win32\sys\mman.h"\
+	
+
+"$(INTDIR)\mmap.obj" : $(SOURCE) $(DEP_CPP_MMAP) "$(INTDIR)"
 	$(CPP) $(CPP_PROJ) $(SOURCE)
 
 
diff -u -r -N apache_1.3.22/src/os/win32/mmap.c apache_1.3.22.mmap/src/os/win32/mmap.c
--- apache_1.3.22/src/os/win32/mmap.c	Thu Jan  1 09:00:00 1970
+++ apache_1.3.22.mmap/src/os/win32/mmap.c	Fri Oct 19 10:47:52 2001
@@ -0,0 +1,220 @@
+/*
+
+    mmap functions for Windows
+
+    this functionality only for Apache 1.3.x
+
+    bero@bekkoame.ne.jp
+
+*/
+
+#include <windows.h>
+#include <io.h>
+#include <errno.h>
+#include <stdlib.h> /* for malloc */
+#include <sys/mman.h>
+
+#define HIDWORD(off)    (0)
+#define LODWORD(off)    (off)
+#define set_errno(no)   errno = no
+
+
+/*
+    address -> memory mapping object 
+*/
+
+struct mmap_list_t {
+    HANDLE hMap;
+    caddr_t addr;
+    struct mmap_list_t *next;
+};
+
+static struct mmap_list_t *top = NULL;
+static HANDLE mmap_list_mutex = NULL;
+
+static int mmap_add(HANDLE hMap,caddr_t addr)
+{
+    struct mmap_list_t *cur;
+
+    /* first */
+    if (mmap_list_mutex==NULL) {
+        /* this mutex is automaticaly closed by OS when process end */
+        mmap_list_mutex = CreateMutex(NULL,FALSE,NULL);
+        if (mmap_list_mutex == NULL) return -1;
+    }
+
+    cur = malloc(sizeof(struct mmap_list_t));
+
+    WaitForSingleObject(mmap_list_mutex,INFINITE);
+
+    cur->hMap = hMap;
+    cur->addr = addr;
+    cur->next = top;
+    top = cur;
+
+    ReleaseMutex(mmap_list_mutex);
+
+    return 0;
+}
+
+static HANDLE mmap_search_delete(caddr_t addr)
+{
+    struct mmap_list_t *cur,*prev;
+    HANDLE ret;
+
+    WaitForSingleObject(mmap_list_mutex,INFINITE);
+
+    for(prev=NULL,cur = top;cur && cur->addr!=addr;prev=cur,cur=cur->next) ;
+
+    if (cur==NULL) {
+        ret = NULL;
+    } else {
+        ret = cur->hMap;
+        if (prev) {
+            prev->next = cur->next;
+        } else {
+            top = cur->next;
+        }
+        free(cur);
+    }
+
+    ReleaseMutex(mmap_list_mutex);
+
+    return ret;
+}
+
+
+/*
+    main
+*/
+
+caddr_t mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t off)
+{
+    HANDLE hFile;
+    HANDLE hMap;
+    DWORD access,protect;
+    size_t maxsize = len; /* 0 means filesize */
+    caddr_t ret;
+
+    static DWORD granularity,pagesize;
+
+    /* get pagesize */
+    if (!granularity) {
+        SYSTEM_INFO si;
+        GetSystemInfo (&si);
+        granularity = si.dwAllocationGranularity;
+        pagesize = si.dwPageSize;
+    }
+
+    /* check param */
+    if (off % pagesize
+    || (!(flags & MAP_SHARED) && !(flags & MAP_PRIVATE))
+    || ((flags & MAP_SHARED) && (flags & MAP_PRIVATE))
+    || ((flags & MAP_FIXED) && ((DWORD)addr % granularity))
+    || len==0
+    || prot&PROT_EXEC)
+    {
+        set_errno (EINVAL);
+        return MAP_FAILED;
+    }
+
+    /* convert mmap param to windows param */
+    if (prot&(PROT_READ|PROT_WRITE)==PROT_READ) {
+        access = FILE_MAP_READ;
+        protect = PAGE_READONLY;
+    } else if (prot&(PROT_READ|PROT_WRITE)==(PROT_READ|PROT_WRITE)) {
+        if (flags&MAP_PRIVATE) {
+            access = FILE_MAP_COPY;
+            protect = PAGE_WRITECOPY;
+        } else {
+            access = FILE_MAP_WRITE;
+            protect = PAGE_READWRITE;
+        }
+    }
+
+    if (flags & MAP_ANONYMOUS) fd = -1;
+
+    if (fd==-1) {
+        hFile = INVALID_HANDLE_VALUE;
+    } else {
+        hFile = (HANDLE)_get_osfhandle(fd);
+    }
+
+    hMap = CreateFileMapping(hFile,NULL,protect,HIDWORD(maxsize),LODWORD(maxsize),NULL /* no name*/);
+
+    if (hMap!=NULL) {
+        ret = (caddr_t)MapViewOfFileEx(hMap,access,HIDWORD(off),LODWORD(off),len,addr);
+        if (ret!=NULL) {
+            if (!(flags&MAP_FIXED) || ret==addr) {
+                if (mmap_add(hMap,ret)==0)
+                    return ret; /* success */
+            }
+            UnmapViewOfFile(ret);
+        }
+        CloseHandle(hMap);
+    }
+    return MAP_FAILED;
+
+}
+
+int munmap (caddr_t addr, size_t len)
+{
+    HANDLE hMap;
+
+    if (UnmapViewOfFile(addr)!=0) {
+        hMap = mmap_search_delete(addr);
+        if (hMap!=NULL) {;
+            if (CloseHandle(hMap)!=0) {
+                return 0;   /* success */
+            }
+        }
+    }
+    return -1;
+}
+
+#if 0
+int mprotect (caddr_t addr, size_t len, int prot)
+{
+    DWORD old_prot,new_prot;
+
+    switch (prot) {
+    case PROT_NONE:
+        new_prot = PAGE_NOACCESS;
+        break;
+    case PROT_READ | PROT_WRITE | PROT_EXEC:
+        new_prot = PAGE_EXECUTE_READWRITE;
+        break;
+    case PROT_READ | PROT_WRITE:
+        new_prot = PAGE_READWRITE;
+        break;
+    case PROT_READ | PROT_EXEC:
+        new_prot = PAGE_EXECUTE_READ;
+        break;
+    case PROT_READ:
+        new_prot = PAGE_READONLY;
+        break;
+    case PROT_EXEC:
+        new_prot = PAGE_EXECUTE;
+        break;
+    default:
+        set_errno (EINVAL);
+        return -1;
+    }
+
+    if (VirtualProtect(addr,len,new_prot,&old_prot)==0) {
+        set_errno(EACCES);
+        return -1;
+    }
+    return 0;
+}
+
+
+int msync (caddr_t addr, size_t len, int flags)
+{
+    if (FlushViewOfFile(addr,len)==0) {
+        set_errno(EINVAL);
+        return -1;
+    }
+    return 0;
+}
+#endif
diff -u -r -N apache_1.3.22/src/os/win32/os.h apache_1.3.22.mmap/src/os/win32/os.h
--- apache_1.3.22/src/os/win32/os.h	Wed Sep 26 23:40:13 2001
+++ apache_1.3.22.mmap/src/os/win32/os.h	Thu Oct 18 09:05:42 2001
@@ -112,8 +112,9 @@
 #define NO_TIMES
 #define NO_GETTIMEOFDAY
 #define USE_LONGJMP
-#define HAVE_MMAP
+#define HAVE_MMAP 1
 #define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
 #define MULTITHREAD
 #define HAVE_CANONICAL_FILENAME
 #define HAVE_DRIVE_LETTERS
diff -u -r -N apache_1.3.22/src/os/win32/sys/mman.h apache_1.3.22.mmap/src/os/win32/sys/mman.h
--- apache_1.3.22/src/os/win32/sys/mman.h	Thu Jan  1 09:00:00 1970
+++ apache_1.3.22.mmap/src/os/win32/sys/mman.h	Thu Oct 18 15:14:58 2001
@@ -0,0 +1,54 @@
+/* sys/mman.h
+
+   Copyright 1996, 1997, 1998, 2000, 2001 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifndef _SYS_MMAN_H_
+#define _SYS_MMAN_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stddef.h>
+#include <sys/types.h>
+
+typedef char* caddr_t;
+
+#define PROT_NONE 0
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define PROT_EXEC 4
+
+//#define MAP_FILE 0
+#define MAP_SHARED 1
+#define MAP_PRIVATE 2
+//#define MAP_TYPE 0xF
+#define MAP_FIXED 0x10
+#define MAP_ANONYMOUS 0x20
+#define MAP_ANON MAP_ANONYMOUS
+
+#define MAP_FAILED ((caddr_t)-1)
+
+/*
+ * Flags for msync.
+ */
+#define MS_ASYNC 1
+#define MS_SYNC 2
+#define MS_INVALIDATE 4
+
+extern caddr_t mmap (caddr_t __addr, size_t __len, int __prot, int __flags, int __fd, off_t __off);
+extern int munmap (caddr_t __addr, size_t __len);
+extern int mprotect (caddr_t __addr, size_t __len, int __prot);
+extern int msync (caddr_t __addr, size_t __len, int __flags);
+
+#ifdef __cplusplus
+};
+#endif /* __cplusplus */
+
+#endif /*  _SYS_MMAN_H_ */
>Release-Note:
>Audit-Trail:
>Unformatted:
 [In order for any reply to be added to the PR database, you need]
 [to include <ap...@Apache.Org> in the Cc line and make sure the]
 [subject line starts with the report component and number, with ]
 [or without any 'Re:' prefixes (such as "general/1098:" or      ]
 ["Re: general/1098:").  If the subject doesn't match this       ]
 [pattern, your message will be misfiled and ignored.  The       ]
 ["apbugs" address is not added to the Cc line of messages from  ]
 [the database automatically because of the potential for mail   ]
 [loops.  If you do not include this Cc, your reply may be ig-   ]
 [nored unless you are responding to an explicit request from a  ]
 [developer.  Reply only with text; DO NOT SEND ATTACHMENTS!     ]