WebObjects 5.1: How to Improve Performance of IIS Adaptor on Microsoft Windows

Under certain conditions, the IIS adaptor on Microsoft Windows experiences a degradation in performance. This document describes the issue in detail and provides source code that can be used to prevent it.
Symptom

When using the IIS adaptor, the performance degrades under certain conditions. These conditions cause large amounts of memory to be allocated for each request resulting in poor response times and OutOfMemoryExceptions.

Note: This happens whenever the ISAPI adaptor is used, even when your applications are used on another computer with a different operating system.


Solution


Important: This patch is for Microsoft Windows only. Do not use this patch on other platforms.

How to apply the code patch


File request.h

In request.h, search for #include "WOURLCUtilities.h" and add the following line below it:

#include "wastring.h"

File request.c

In request.c, search for the beginning of the method 'int req_sendRequest' (around line 217). Be careful not to delete this original method 'int req_sendRequest'. Add the following code block before the original method 'int req_sendRequest':

#ifdef WIN32 
static void req_appendHeader(const char *key, const char *val, String *headers) { 
  int valLength = strlen(val); 
  while (val[valLength - 1] == '\\r' || val[valLength - 1] == '\\n') { 
    valLength--; 
  } 
  str_append(headers, key); 
  str_appendLiteral(headers, ": "); 
  str_appendLength(headers, val, valLength); 
  str_appendLiteral(headers, "\\r\\n"); 
} 

int req_sendRequest(HTTPRequest *req, net_fd socket) { 
  struct iovec *buffers; 
  int bufferCount, result; 
  String *headersString; 

  buffers = WOMALLOC(3 * sizeof(struct iovec)); 

  headersString = str_create(req->request_str, 0); 
  if (headersString) { 
    st_perform(req->headers, (st_perform_callback)req_appendHeader, headersString); 
  } 
  buffers[0].iov_base = headersString->text; 
  buffers[0].iov_len = headersString->length; 
  buffers[1].iov_base = "\\r\\n"; 
  buffers[1].iov_len = 2; 
  bufferCount = 2; 
  if (req->content_length > 0) { 
    bufferCount++; 
    buffers[2].iov_base = req->content; 
    buffers[2].iov_len = req->content_length; 
  } 
  result = transport->sendBuffers(socket, buffers, bufferCount); 
  str_free(headersString); 
  WOFREE(buffers); 
  if (result == 0) 
    result = transport->flush_connection(socket); 
  else 
    WOLog(WO_ERR, "error sending request"); 

  return result; 
} 
#else 
// End of the code to be added to request.c

After the #else comes the original req_sendRequest method.

Go to the end of this method and insert #endif on the next line after the closing brace.

4. Compile the adaptor.

The makefile expects the OS environment variable to be either empty or contain the string 'WINDOWS'.

You can explicitly set the OS variable in a Bourne shell using the following:

cd $NEXT_ROOT/Developer/Examples/WebObjects/Source/Adaptors
set OS=WINDOWS
make clean
make  
make IIS

Notes:


5. Install the modified adaptor.

After compilation, the two files WebObjects.EXE (located in $NEXT_ROOT/Developer/Examples/WebObjects/Source/Adaptors/CGI) and WebObjects.DLL (located in $NEXT_ROOT/Developer/Examples/WebObjects/Source/Adaptors/IIS) should be copied to the proper location. Change c:\\inetpub to match your system.

In a Bourne shell, do the following:

cd $NEXT_ROOT/Developer/Examples/WebObjects/Source/Adaptors

net stop w3svc

cp cgi/webobjects.exe c:/inetpub/scripts

cp iis/webobjects.dll c:/inetpub/scripts

net start w3svc

Stopping IIS before copying prevents possible sharing violations for the ISAPI adaptor since you cannot overwrite the file if it has already been loaded by IIS.

Published Date: Feb 19, 2012