★ wanayoo — archive 1999 http://developer.iplanet.com/viewsource/lazar_cgi.htmlNouvelle recherche | Portail wanayoo
iPlanet

You are here:  Home > Developers > View Source Articles > Server-Side JavaScript View Source Article
Server-Side JavaScript View Source Article
 iPlanet Developers


Developer Program
  Membership
  One-to-One Support
  Newsgroups
  Member Services

Developer Publications
  View Source
  Developer News

Documentation
  Technical Manuals
  White Papers
  TechNotes
  Sample Code
  FAQs
  Books

Technologies
  Application Server   CSS
  DOM
  CORBA
  Directory & LDAP
  Dynamic HTML
  Java
  JavaScript
  Linux
  RDF
  Security
  SSJS
  XML
  XUL

Developer Downloads
  Tools & SDKs
  Patches

iPlanet Products
  Technical Resources










spacer
CGI vs. Server-Side JavaScript for Database Applications

By Z. Peter Lazar and Peter Holfelder


Send comments and questions about this article to View Source.
Click here for printer-friendly version  

[Editor's Note: This article was initially prepared using server-side JavaScript programming techniques in the Enterprise Server 2.0 and LiveWire 1.01. The authors upgraded the code to new server-side JavaScript methods available with Enterprise Server 3.0, accomplishing their upgrade in less than one week. Additionally, they experienced improved performance using Enterprise Server 3.0 compared with Enterprise Server 2.0.

This article assumes some knowledge of Web-based database access programming concepts. Several earlier View Source articles can introduce you to some of the concepts covered here. If you're unfamiliar with server-side JavaScript, please see the article "JavaScript on the Server: Internet Application Development Without Native Code." For a general overview of Enterprise Server 3.0 and its new features, see "Enterprise Server 3.0: Industrial-Strength Server Software"; new server-side JavaScript features in Enterprise Server 3.0 are described in "Writing Database Applications With Enterprise Server 3.0."]

Despite recent advances in specialized, Web-database connectivity tools, many developers still use traditional CGI and Perl-based methods for dynamically presenting data on the Web. What advantages do more recent Web-database middleware have over traditional CGI programming? In this article we attempt to answer that question by comparing traditional CGI to the LiveWire database connectivity component of Netscape's Enterprise Server 3.0, which uses server-side JavaScript.

We will begin by examining the architectural differences between traditional CGI and server-side JavaScript database development. Then we will present, in turn, two example programs - one implemented using the CGI method of Web-database connectivity and a functionally equivalent program implemented in server-side JavaScript under Netscape Enterprise Server 3.0. We will compare the two approaches in terms of portability, extendability, and code maintainability.

Finally, we will present performance measurements taken from running the CGI and server-side JavaScript-based example programs in identical environments under various loads.

THE SYSTEM ARCHITECTURES

There are two fundamental reasons for selecting one database architecture over another:

  • Performance - how fast the Web interface performs in a production environment
  • Data maintainability - how easily the database data seen by Web users can be kept up to date

Here we will look at how the traditional CGI and LiveWire/server-side JavaScript architectures stack up in terms of performance and data maintainability.

A Traditional CGI-Based System Using Perl

CGI programming with Perl is probably the most prevalent method for displaying relational database data on the Web. Perl by itself doesn't contain built-in database connectivity features, but extension products facilitate indirect or direct database access from Perl. Some of these extensions offer dynamic database access and are quite efficient. In this article, though, we will discuss the less efficient but more common technique in which the Perl script retrieves database information indirectly from a text file (Figure 1).


Figure 1. Traditional CGI Architecture Using Perl


In this approach, the database periodically dumps a table or a view into a tab-delimited text file. The database schedules this dump regularly or triggers it whenever data in the underlying tables changes. Unchanging Web pages are implemented by static HTML files, but Perl scripts use tab-delimited text files to dynamically generate any HTML pages based on database data.

In the static CGI approach, the Web server must load, execute, and terminate a new CGI program for each user access. Under heavy server loads, this can seriously degrade performance. Also, the approach involves extra processing and file I/O whenever data updates require rebuilding the text file.

Large data sets and complex queries especially burden the system because data querying must take place in the CGI program rather than in the database. Rather than delegate complex queries to a relational database on another machine, the CGI program itself must perform such complex operations based on the text file data.

The human time and effort required to maintain data using the static CGI approach presents problems more serious than poor performance. At any time, the copy of the database used by the Perl script may be out of date. Also, the architecture doesn't allow for direct database update via the Web. Inevitably, system maintainers will need to manually update data and resolve problems resulting from unsynchronized data.

A JavaScript-Based System Using Netscape Enterprise Server 3.0 and LiveWire

Because server-side JavaScript generates HTML dynamically from the database as requested by the browser (Figure 2), it interfaces databases to the Web more effectively than the traditional CGI approach. The user interface in HTML and application logic in JavaScript reside in the same file. Server-side JavaScript is identical to the industry-standard client-side JavaScript developed by Netscape and Sun except that it contains database connectivity, state maintenance, and other back-end features. At run time, Enterprise Server 3.0 interprets these files, incorporates live database data, and sends HTML back to the Web browser.


Figure 2. LiveWire/Server-Side JavaScript Architecture


Server-side JavaScript runs in the Netscape Web server process and shares a configurable number of open database connections among all users. This requires fewer system resources than the multiple short-lived processes of the CGI approach. Also, as long as the Web server and database are running, there is no need to establish and terminate costly database connections.

Unlike the traditional CGI approach, server-side JavaScript improves data maintenance by directly translating database data to HTML as requested by the browser. If database data changes, the subsequent Web access immediately sees this change. Furthermore, JavaScript improves data maintainability because it enables direct database updating via the Web.

To summarize, tight integration with the Web server and relational database improves performance of a Web-database solution. Traditional CGI weakly integrates with the Web server because each Web access spawns a new process and establishes a new database connection. Server-side JavaScript is more tightly integrated because it runs in the Web server process and shares database connections across all Web accesses.

Traditional CGI and JavaScript also incur different levels of data maintenance effort. Maintaining database data using the traditional CGI approach can be very expensive because it requires managing and synchronizing multiple copies of data. JavaScript reduces data maintenance costs because data is stored in only one place and accessed dynamically by the Web browser.

CGI AND JAVASCRIPT DEVELOPMENT

Now that we've reviewed the architectural differences between CGI and JavaScript applications that are already running, we will focus on the development efforts required to get to that point.

To compare and contrast traditional CGI to JavaScript development, we created functionally equivalent database applications using both approaches. Using the example program's source code as a starting point, we will describe the level of portability, extendability, and code maintainability inherent in each approach.

There are four aspects of portability that affect the cost effectiveness of a particular development tool for Web-database connectivity:

  • portability of the development tool across platforms
  • ease of development tool installation
  • portability of the development tool across Web servers
  • portability of the application source code across platforms

Extendability in this context is a function of the ease with which more sophisticated database operations can be added to an application, and the ease with which a developer can precisely control the format of the output HTML.

The maintainability issues that we examine for this class of applications are the ease of source code maintenance and the ease of splitting work between graphic designers and programmers.

About Our Example Program

We will implement a simple three-page dynamic Web site in both Perl and JavaScript.

  • The first page of the site will be a static HTML page that serves as the "home page" for the site.
  • The home page links to the "category page," which contains a dynamically generated list of hyperlinked product categories such as laptops, printers, and monitors.
  • The "product page" is reached by selecting one of the hyperlinks on the category page. It contains a list of products pertaining to the selected category. For instance, if the user selects the laptops hyperlink on the category page, the browser will send an HTTP request with a category ID of 1 back to the application, which will then generate a list of all laptops.

The database that underlies the program consists of two tables, CATEGORY and PRODUCT. The CATEGORY table has two fields, CategoryID and CategoryName. CategoryID is a numeric field that is the primary key for the CATEGORY table; CategoryName is a string that describes the product category. The PRODUCT table has three fields, ProductID, CategoryID, and ProductName. ProductID is the key field of the PRODUCT table, CategoryID is a foreign key to the CATEGORY table, and ProductName is a string that describes an individual product in the category.

Our Example as a Traditional CGI-Based System Using Perl

Perl source code is plain text and thus can be created with any text editor. No special server configuration is needed to run a Perl script under CGI. The Perl version of the site contains three files:

  • A static HTML file for the home page (Listing 1).
  • The Perl scripts category.pl and product.pl, to generate the category page and the product page, respectively. The scripts obtain data from two tab-delimited text files, which correspond to the two tables used in the server-side JavaScript environment.


Listing 1. The HTML file for the Perl home page

<!--
///////////////////////////////////////////////////////////////////////////
//      Perl.html - Perl Home Page
///////////////////////////////////////////////////////////////////////////
-->
<TITLE> Perl Home Page </TITLE></HEAD>
<BODY>
<H2>List Generated Dynamically from Database Using Perl</H2>
<P>Click <A HREF=/old?u=http%3A%2F%2Fdeveloper.iplanet.com%2Fviewsource%2Fcategory.pl&y=1999>here</A> to generate a list of hyperlinks 
from the CATEGORY table.
</BODY>
</HTML>


The category.pl script (Listing 2) prints the header of an HTML page. Note that the programmer must send the "Content-type: text/html" line explicitly (this is done automatically with server-side JavaScript). After sending the header, the script opens the text file containing the category data. It reads each line of the file, splits the "record" into two "fields" on the tab character, and checks that each required field exists. It then places the category ID and category name into separate arrays and closes the text file. If any line contains an error, the script writes an error message to the output HTML and quits. If the data in the file was read successfully, the script dynamically creates a hyperlink for each category. The hyperlinks point to the product.pl script and include a category ID value that product.pl will use to select the products to display. Finally, the script prints an HTML footer.


Listing 2. The Perl script for the category page

#!/usr/bin/perl
# category.pl - Perl implementation of category page

&print_HTML_header();
# Open the category.txt file.
open (CATEGORY, "category.txt") || &print_error("Error: cannot open CATEGORY table.");

# Read each line of the file, checking for bad records.
$records = -1;
while (!eof(CATEGORY)) {
   $line = <CATEGORY>;
   ($ID, $dummy, $Category, @dummy) = split ('\t', $line); 
   if (($ID ne "") && ($Category ne "")) {
      $records++;
      $IDs[$records] = $ID;
      $Categories[$records] = $Category;
   }
   else {
      $records = -1;
      $errMessage = "Error: bad record in CATEGORY table.";
      last;
   }
}
# Close the category.txt file.
close (CATEGORY);
# Make sure we found some records. If we did, print instructions
# for following the links.
if ($records > -1) {
   print 
      "<H2>List of Categories</H2>
      <P>Follow any of the hyperlinks in the list to view a list
         of products in that category.
      <UL>\n";
}
else {
   &print_error($errMessage);
}
# Generate hyperlinks for each of the records.
for ($a = 0; $a <= $records; $a++) {
   print "   <LI><A HREF=/old?u=http%3A%2F%2Fdeveloper.iplanet.com%2Fviewsource%2F%5C&y=1999"http://localhost/cgi-bin/w3j/product.pl?ID=", 
         $IDs[$a],
         "\">",
         $Categories[$a],
         "</A>\n";
}
# If there were any records to print, close the unordered list, and
# print the HTML footer.
if ($records > -1) {
   print "</UL>\n";
}
&print_HTML_footer();
return 0;

sub print_HTML_header {
   print 
        "Content-type: text/html

        <HTML>
        <HEAD>
           <TITLE>A simple database application in Perl: Category page</TITLE>
        </HEAD>
        <BODY>\n";
}

sub print_error {
   $errString = @_;
   print "$errString\n";
   &print_HTML_footer;
   exit;
}

sub print_HTML_footer {
   print "</BODY>
          </HTML>\n";
}


The product.pl script (Listing 3) also prints the header of an HTML page. It then obtains the query string from the CGI QUERY_STRING environment variable and parses it (this is an automatic process in server-side JavaScript). If the query string parses correctly, the script opens the text file containing the product data. It reads each line of the file, splits the record into three fields on the tab character, and checks that each required field exists. If the category ID field matches the category ID passed to the script via CGI, the product's name is placed into an array. If the data in the file was read successfully, the script creates a list element for each matching product and then prints an HTML footer.


Listing 3. The Perl script for the product page

#!/usr/bin/perl
# product.pl - Perl implementation of product page
#
# This page displays a list of products that correspond with the category 
# selected from the category page.
&print_HTML_header();
# Retrieve the query string.
$query = $ENV{'QUERY_STRING'};
if ($query eq "") {
   &print_error("Error: no query sent to script.");
}
# Parse the query string. We are doing the most minimal parsing,
# assuming that there is only one key/value pair, that the key is
# the proper key, and that there are no escaped characters in
# the key or value.
($dummy, $queryID) = split ('=', $query);
if ($dummy ne 'ID' || $queryID eq "") {
   &print_error("Error: incorrect query.");
}
# Open the product.txt file.
open (PRODUCT, "product.txt") || print "Error: cannot open PRODUCT table.\n";

# Read each line of the file, checking for bad records.
$records = -1;
while (<PRODUCT>) {
   $line = $_;
   ($dummy, $dummy, $ID, $dummy, $Product, @dummy) = split ('\t', $line); 
   if (($ID ne "") && ($Product ne "")) {
      if ($ID == $queryID) {
         $records++;
         $IDs[$records] = $ID;
         $Products[$records] = $Product;
      }
   }
   else {
      $errMessage = "Error: bad record in PRODUCT table\n";
      $records = -1;
      last;
   }
}

# Close the category.txt file.
close (PRODUCT);

# Make sure we found some records. If we did, print instructions
# for following the links.
if ($records > -1) {
   print 
      "<H2>List of Products</H2>
      <UL>\n";
}
else {
   &print_error('Error: no records found in the PRODUCT table.');
}

# Generate hyperlinks for each of the records.
for ($a = 0; $a <= $records; $a++) {
   print "   <LI>$Products[$a]\n"; 
}
print "</UL>\n";
&print_HTML_footer();
return 0;

sub print_HTML_header {
   print 
   "Content-type: text/html

   <HTML>
   <HEAD>
      <TITLE>A simple database application in Perl: Product page</TITLE>
   </HEAD>
   <BODY>\n";
}

sub print_error {
   $errString = @_;
   print "$errString\n";
   &print_HTML_footer();
   exit;
}

sub print_HTML_footer {
   print "</BODY>
          </HTML>";
}


Perl as a development tool has clear advantages in terms of portability:

  • It can be installed on all popular versions of UNIX. This includes the freeware Linux and FreeBSD, which commercial products generally do not support. Perl is also available for 32- and 16-bit versions of Windows, Mac OS, VMS, and the IBM AS400. Perl installs automatically on UNIX and many other operating systems (but the installation can be time-consuming compared to the LiveWire database connectivity component that is part of Enterprise Server 3.0).
  • Perl scripts and other traditional CGI applications have very high portability across Web servers. Practically all commercial and freeware Web servers in common use have implemented CGI, which is an open standard.
  • Portability of application source code is also very high with Perl, although two issues stand out: ports of Perl to non-UNIX systems may not support Perl features that are closely tied to that operating system (not a major concern with a text-file database); and the specification of pathnames may need to be changed to meet the conventions of the local system.

Using Perl with character-delimited copies of database tables limits its extendability. Without built-in SQL support provided by specialized database connectivity extensions, database operations such as JOINs and complex SELECT statements spanning multiple tables require complex programming. The indirect database access method also makes it difficult to extend the system so that Web users can update database data. Extendability in terms of formatting output HTML is high, however, since traditional CGI programs do not separate HTML formatting from the program itself.

Code is easy to follow in the traditional CGI approach because there are few components and concepts. This simplicity enhances maintainability, especially when the maintainer is not the original developer. On the other hand, developers must program at a lower level than with development approaches such as server-side JavaScript. Many specialized functions that come with JavaScript would need to be coded manually or obtained from third-pary libraries when the coding is done in Perl using the traditional CGI approach.

The maintainability of a traditional CGI application will depend on the features of the language used to implement it. In the case of Perl, its functions and objects aid maintainability. Its main maintainability drawbacks are the somewhat cryptic regular expression matching statements and predefined variables in versions 4 and earlier. In the traditional CGI environment, formatting is not distinct from functionality; the HTML created by the script is partially or completely embedded in the scripts. Consequently, a graphic artist cannot use his or her favorite WYSIWYG editor to modify the user interface layout.

Our Example Using JavaScript

JavaScript source code, like Perl, is plain text. It is either embedded within special tags in an otherwise standard HTML file or placed by itself in plain text files. JavaScript source code needs to be compiled into a proprietary format to be used by the Application Manager of the Enterprise Server 3.0, which requires some simple configuration.

The JavaScript source code is divided into four HTML files, one for each of the three pages that the user will see plus an "initial page." The initial page (Listing 4) is processed by the Web server when the application is first accessed by a user. It typically contains code to connect to databases and definitions for properties of the JavaScript project object, which exists as long as the application is running on the server. JavaScript applications run in a separate server thread and are not terminated when there are no connections, so the project object persists as long as the Web server is running.


Listing 4. The "initial page" for the JavaScript example program

<SERVER>
////////////////////////////////////////////////////////////////////////
///
//      project.html - LiveWire and Server-Side JavaScript Implementation
//
//  Example applications project file.  Establishes database connections 
//  shared by all users of example application.
////////////////////////////////////////////////////////////////////////
///
if (project.productDB == null) {
   project.lock();
   project.productDB = new Object();
   project.productDB.pool =
     new DbPool("ODBC", "PRODUCT", "plazar", "plazar", " ", 5, false);
   project.unlock();
}
</SERVER>


The initial page consists entirely of server-side JavaScript code. It checks for an existing database connection; if none exists, which is the expected result, it locks the project object, so that no other clients can change any properties of the project object. The application then establishes a pool of five connections to the database for a particular database user (in this case via an ODBC connection to a SQL Server database running on a dedicated server). After this one-time execution of the initial page following project startup, Netscape Enterprise Server 3.0 shares the connections with all subsequent user accesses. This is one of the simpler methods of establishing database connectivity with Enterprise Server 3.0. More sophisticated methods such as using multiple pools of database connections in a single application are discussed in the Netscape document Writing Server-Side JavaScript Applications.

The home page for our application (Listing 5) is a static HTML page that contains a single hyperlink to the category page.


Listing 5. The HTML file for the JavaScript home page

<HTML><HEAD>

<!--
////////////////////////////////////////////////////////////////////////
///
//      LiveWire.html - LiveWire and Server-Side JavaScript Home Page
////////////////////////////////////////////////////////////////////////
///
-->
<TITLE> LiveWire and Server-Side JavaScript Home Page
</TITLE></HEAD>
<BODY>
<H2>List Generated Dynamically from Database Using Netscape
Enterprise Server 3.0's Server-Side JavaScript and LiveWire</H2>
<P>Click <A HREF=/old?u=http%3A%2F%2Fdeveloper.iplanet.com%2Fviewsource%2Flw_category.html&y=1999>here</A> to generate a list of 
hyperlinks from the CATEGORY table.
</BODY>
</HTML>


The category page (Listing 6) contains server-side JavaScript between a static HTML header and footer. After serving the header, the application checks whether database connectivity has been established. If so, the application requests a connection. It then begins a database transaction and executes a predefined SQL query. Enterprise Server places the results of the query into a database cursor object. The application then dynamically generates a hyperlink for each record returned in the cursor. Finally, the application closes the cursor, commits the database transaction, releases the connection, and sends the rest of the static HTML.


Listing 6. The HTML file for the JavaScript category page

<HTML><HEAD>
<SERVER>
////////////////////////////////////////////////////////////////////////
///
//  lw_category.html - LiveWire and Server-Side JavaScript Implementation
//
//  This page displays a list of categories from the CATEGORY table. 
//  The category names are hyperlinked and lead to a page with associated
//  products from the PRODUCT table.
////////////////////////////////////////////////////////////////////////
///
</SERVER>
<TITLE>Categories</TITLE>
</HEAD><BODY>
<P> <B>Select a Category:</B>
<UL>
<SERVER>

if (project.productDB.pool.connected()) { 
    var conn = project.productDB.pool.connection("conn", 60);

    conn.beginTransaction();
    qs = "SELECT category_id, category_name from CATEGORY"; 
    results = conn.cursor(qs);
    while (results.next()) {
          write("<LI><A HREF=/old?u=http%3A%2F%2Fdeveloper.iplanet.com%2Fviewsource%2F%5C&y=1999"lw_product.html?category_id="+results.category_id+"\">"
          +results.category_name+"</A>\n");
    }
    results.close();
    conn.commitTransaction();   
    conn.release();
}
else {
    write("<p>Database connection failed");
}</SERVER></UL>
</CENTER>
</BODY></HTML>


When the product page (Listing 7) is accessed, the JavaScript runtime engine automatically decodes the key-value pairs in the CGI transaction and makes them properties of its Request object. The product page uses the value of the Request object's CategoryID property (which directly corresponds to the CategoryID passed to the product page via the URL on the category page) to generate an SQL query. Enterprise Server places the result of the query into a cursor object and dynamically lists a product for each record returned in the cursor. Finally, as with the category page, the application closes the cursor, commits the database transaction, releases the connection, and sends the rest of the static HTML.


Listing 7. The HTML file for the JavaScript product page

<HTML><HEAD>
<SERVER>
////////////////////////////////////////////////////////////////////////
///
//  lw_product.html - LiveWire and Server-Side JavaScript Implementation
//
//  This page displays a list of products from the PRODUCT table
//  for a given category_id. 
////////////////////////////////////////////////////////////////////////
///
</SERVER>
<TITLE>Categories</TITLE>
</HEAD><BODY>
<P>
<UL>
<SERVER>

if (project.productDB.pool.connected()) {
   var iCategoryID = request.category_id;
   var conn = project.productDB.pool.connection("conn", 60);

   conn.beginTransaction();
   qs = "SELECT product_name from PRODUCT WHERE category_id =" + iCategoryID; 
   results = conn.cursor(qs);
   while (results.next()) {
         write("<LI>"+results.product_name+"</A>\n");
   }
   results.close();
   conn.commitTransaction();
   conn.release();   
}
else {
        write("<p>Database connection failed");
}</SERVER></UL>
</BODY></HTML>


The LiveWire/server-side JavaScript application environment is portable between Windows NT and several UNIX platforms. It installs quickly and automatically, and configuring and running applications under the environment is a simple process. In addition, the JavaScript source code is fully portable between all supported platforms (but pathname references must adhere to local path naming conventions). The portability drawback of server-side JavaScript with LiveWire database connectivity is that it can only be used with Netscape Enterprise Server.

LiveWire's sophisticated database features and programmatic development approach make it very extendable. SQL support gives server-side JavaScript developers the ability to perform sophisticated database functions, including JOINs and complex multiple-table SELECTs, INSERTs, UPDATEs, and DELETEs. Integration of database cursors, functions, and looping constructs into the HTML file give server-side JavaScript programmers detailed control over the HTML formatting of database data. Powerful database functionality combined with precise control of the appearance of HTML output enhances extendability.

LiveWire's support of JavaScript functions and user-defined objects helps developers produce clear, maintainable code. Also, in LiveWire, HTML formatting is distinct from functionality. All JavaScript code is embedded in <SERVER> and </SERVER> tags so that it doesn't interfere with WYSIWYG HTML editors. Consequently, a graphic artist doesn't have to use coding tools or know how to code in JavaScript to modify user interface layout.

A Review of How the Approaches Compare

Both discussed approaches to Web-database connectivity require a minimum of code modification when ported to other platforms, and while ease of development tool installation varies, it is a one-time cost. A traditional CGI application using Perl can be run on a large number of platforms with a wide variety of Web servers. LiveWire-based applications using Javascript can also run on a number of platforms, but they can only be used with Netscape Enterprise Server.

CGI applications using Perl are difficult to extend with complex database operations. The differences are minor in the simple, two-table database presented in this article; however, more complex databases with multiple-table JOINs present a real problem for the traditional CGI approach. Complex database operations are relatively much easier to implement with server-side JavaScript. They can be performed with embedded SQL statements or even with stored procedure calls to the database.

Perl, as a structured programming language, has all the features necessary to write clear, maintainable code. In Perl, however, there is no clear boundary between static and dynamic HTML in the script, making it difficult to split tasks between developers and graphics professionals. Server-side JavaScript features both structured programming and a clear boundary between static and dynamic HTML.

PERFORMANCE MEASUREMENTS

We performed our tests on a 166 MHz Pentium machine with 32 MB of RAM running Windows NT and Netscape Enterprise Server 3.0. This machine was connected to a 275 MHz DEC Alpha database server with 64 MB RAM running Windows NT and Microsoft SQL Server 6.0.

Our client machine used an automated test tool to time the retrieval of the category and product pages of the CGI and JavaScript sample applications described above. The category page lists all records in the CATEGORY table in sorted order; the product page lists all records in the PRODUCT table for a given category ID (we chose a category ID of 1 for our test). Each test run consisted of five batches of 100 hits. The average time to retrieve each page, in milliseconds, is shown in Table 1.


Table 1. Category page and product page access times

Category page Product page
CGI/Perl 219 ms 5990 ms
LiveWire/JavaScript 198 ms 104 ms



When "dumping" the results of the 182-record CATEGORY table without any filtering, we see that the CGI/Perl method is slightly slower than Enterprise Server 3.0's LiveWire and server-side JavaScript method. This demonstrates that even for such small data sets and relatively simple database operations, the additional database communications overhead of the JavaScript approach is outweighed by other advantages inherent in the Enterprise Server 3.0/LiveWire architecture. Since CGI requires a new process to be spawned for each simultaneous request, we would expect to see performance decrease significantly under multiple simultaneous accesses. This would not be the case for server-side JavaScript because new processes are not spawned by the Netscape Enterprise Manager for additional simultaneous requests.

Once the data set becomes large and requires filtering, however, the performance advantage shifts decidedly toward LiveWire and JavaScript. For the 5637-record PRODUCT table, we see that server-side JavaScript is approximately 60 times faster than the equivalent flat-file CGI/Perl program. The similar performance of the server-side JavaScript and CGI/Perl category pages indicates that process-creation overhead alone is not enough to account for the widely differing performance of the product pages. Rather, it appears that the external database plays a larger role in the higher performance of the JavaScript Product page. This is expected because the data manipulation required for the product page is more complex than is required for the category page.

JavaScript produced the product page more quickly than the category page. This is because the product page displays 1/10 the text of the category page (1412 bytes vs. 12,882 bytes). The product page was produced more quickly even though the underlying PRODUCT table is much larger than the CATEGORY table. The difference in performance indicates that SQL Server's use of indices to select records from a large table occurs extremely quickly, making I/O a more significant factor in overall performance between these two pages than database access.

Incidentally, we also measured performance of a Netscape Enterprise Server 2.0/LiveWire 1.01 implementation of the example program before converting to Enterprise Server 3.0. In Enterprise Server 2.0, the category and product pages consistently clocked around 50 percent and 30 percent slower, respectively, than in Enterprise Server 3.0. The improved performance provides a strong motivation for upgrading from Enterprise Server 2.0 to Enterprise Server 3.0 - especially since the conversion is quite painless.

IN SUMMARY

In this article we described how consolidation of source code into fewer files, with a clear demarcation between static HTML and executable code, aids code maintainability and promotes the separation of tasks between graphic artists and programmers. The ability to pass native SQL and stored procedures directly to a database engine and retrieve results also improves extendability and, when combined with live database connections, results in high data maintainability.

We also quantified the performance advantages of using server-side JavaScript with LiveWire compared to traditional Perl/CGI development by measuring the response times of JavaScript and Perl versions of our example program in an identical environment. Our performance tests showed that when we simply display all records in a small table, there is not much of a performance difference between the JavaScript and traditional CGI approaches. In fact, JavaScript performed slightly slower due to the overhead of accessing a separate COTS database as opposed to directly reading a small flat file in the traditional CGI approach.

According to our tests, server-side JavaScript performs much better (almost 60 times faster in our study) when conducting more complex database selects on large tables. This is due to server-side JavaScript's ability to access powerful COTS relational databases without adding a great deal of overhead.

In summary, our analysis of performance, portability, extendability, and maintainability demonstrates that for constructing large-scale applications, the server-side JavaScript with LiveWire approach is clearly superior to the traditional Perl/CGI approach to Web-database connectivity.


Technical reviewer for this article was Moin Rehman of Netscape Communications.

FURTHER READING


View Source wants your feedback!
Write to us and let us know
what you think of this article.

Z. Peter Lazar is a senior engineer at BTG, Inc. who specializes in interfacing databases to the Web.

Peter Holfelder is a technical lead at BTG Inc. who builds Web back-ends in Perl and JavaScript.

(7.97)


Related Readings:


Any sample code included above is provided for your use on an "AS IS" basis, under the Netscape License Agreement - Terms of Use

spacer spacer


                                                       
iPlanet International | Year 2000 | Site Map | Feedback
Products | Solutions | Support | Services | Download | About Us | Developer
© 2000 Sun-Netscape Alliance. All Rights Reserved  Privacy Policy