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
- Z. Peter Lazar. "Web-Database Connectivity." Dr. Dobb's
Sourcebook, Vol. 22, Issue 15 (May/June 1997).
- Z. Peter Lazar, P. Holfelder. "Web Database Connectivity With
Scripting Languages." World Wide Web Journal, Vol. 2, Issue
2 (Spring 1997).
- J. Deep, P. Holfelder. Developing CGI Applications with Perl.
John Wiley and Sons: New York, New York, 1996.
- C. Varela, D. Nekhayev, P. Chandrasekharan, C. Krishnan, V. Govindan,
D. Modgil, S. Siddiqui, D. Lebedenko, M. Winslett. "DB:
Browsing Object-Oriented Databases over the Web." World Wide
Web Journal, Vol. 1, Issue 1 (Winter 1996).
- Netscape Communications Corporation. Writing
Server-Side Javascript Applications.
- Netscape Communications Corporation. "Netscape
Enterprise Server and Enterprise Server Pro."
- Netscape Communications Corporation. Netscape
DevEdge Online FAQs.
- M. Morgan. Special Edition: Using Netscape LiveWire. Que Corporation,
1996.
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