| |||||||
| ------------------------------------------------------ Copyright 2002-2008 hi5 Networks, Inc. All rights reserved. 55 Second Street, Suite 300, San Francisco, CA 94105 Privacy Policy | Unsubscribe | Terms of Service |
By Chandrashekhar
| |||||||
| ------------------------------------------------------ Copyright 2002-2008 hi5 Networks, Inc. All rights reserved. 55 Second Street, Suite 300, San Francisco, CA 94105 Privacy Policy | Unsubscribe | Terms of Service |
|
| ------------------------------------------------------ Copyright 2002-2008 hi5 Networks, Inc. All rights reserved. 55 Second Street, Suite 300, San Francisco, CA 94105 Privacy Policy | Unsubscribe | Terms of Service |
You can use the target parameter in form tag:
<form action="file.html" method="post" target="_blank">
OR
<form action="file.php" method="post" target="foo" onsubmit="window.open(", 'foo', 'width=450,height=300,status=yes,resizable=yes,scrollbars=yes')">
This will open a new window on submit.
Browser class
Identifies the user's Operating system, browser and version
by parsing the HTTP_USER_AGENT string sent to the server
Typical Usage:
require_once($_SERVER['DOCUMENT_ROOT'].'/include/browser.php');
$br = new Browser;
echo "$br->Platform, $br->Name version $br->Version";
For operating systems, it will correctly identify:
Microsoft Windows
MacIntosh
Linux
Anything not determined to be one of the above is considered to by Unix
because most Unix based browsers seem to not report the operating system.
The only known problem here is that, if a HTTP_USER_AGENT string does not
contain the operating system, it will be identified as Unix. For unknown
browsers, this may not be correct.
For browsers, it should correctly identify all versions of:
Amaya
Galeon
iCab
Internet Explorer
For AOL versions it will identify as Internet Explorer (AOL) and the version
will be the AOL version instead of the IE version.
Konqueror
Lynx
Mozilla
Netscape Navigator/Communicator
OmniWeb
Opera
Pocket Internet Explorer for handhelds
Safari
WebTV
Just remove whatever browser conditional you don't need,
change the file uri to your css files,
and add this in each header of your pages
UNDER the main CSS file call
(if not, it won't override the default):
<?php css_add(); ?>
of course, you also need something like that on top:
******************************************************************/
function css_add() {
$br = new Browser;
if ($br->Platform == 'Windows' && $br->Name == 'MSIE') {
if ($br->Version >= 7) {
$css_file = 'add_ie7′;
}
if ($br->Version >= 6 && $br->Version < 7) {
$css_file = 'add_ie6′;
}
if ($br->Version < 6) {
$css_file = 'add_ie5′;
}
} elseif ($br->Name =='Opera') {
$css_file = 'add_opera';
} elseif ($br->Name =='Safari') {
$css_file = 'add_safari';
}
$file_name = './_css/'.$css_file.'.css';
if (file_exists($file_name)) {
echo("<link href=\"".$file_name."\" rel=\"stylesheet\" type=\"text/css\" media=\"screen\" />\r\r");
}
}
/*****************************************************************
*****************************************************************/
class browser{
var $Name = "Unknown";
var $Version = "Unknown";
var $Platform = "Unknown";
var $UserAgent = "Not reported";
var $AOL = false;
function browser(){
$agent = $_SERVER['HTTP_USER_AGENT'];
// initialize properties
$bd['platform'] = "Unknown";
$bd['browser'] = "Unknown";
$bd['version'] = "Unknown";
$this->UserAgent = $agent;
// find operating system
if (eregi("win", $agent))
$bd['platform'] = "Windows";
elseif (eregi("mac", $agent))
$bd['platform'] = "MacIntosh";
elseif (eregi("linux", $agent))
$bd['platform'] = "Linux";
elseif (eregi("OS/2″, $agent))
$bd['platform'] = "OS/2″;
elseif (eregi("BeOS", $agent))
$bd['platform'] = "BeOS";
// test for Opera
if (eregi("opera",$agent)){
$val = stristr($agent, "opera");
if (eregi("/", $val)){
$val = explode("/",$val);
$bd['browser'] = $val[0];
$val = explode(" ",$val[1]);
$bd['version'] = $val[0];
}else{
$val = explode(" ",stristr($val,"opera"));
$bd['browser'] = $val[0];
$bd['version'] = $val[1];
}
// test for WebTV
}elseif(eregi("webtv",$agent)){
$val = explode("/",stristr($agent,"webtv"));
$bd['browser'] = $val[0];
$bd['version'] = $val[1];
// test for MS Internet Explorer version 1
}elseif(eregi("microsoft internet explorer", $agent)){
$bd['browser'] = "MSIE";
$bd['version'] = "1.0″;
$var = stristr($agent, "/");
if (ereg("308|425|426|474|0b1″, $var)){
$bd['version'] = "1.5″;
}
// test for NetPositive
}elseif(eregi("NetPositive", $agent)){
$val = explode("/",stristr($agent,"NetPositive"));
$bd['platform'] = "BeOS";
$bd['browser'] = $val[0];
$bd['version'] = $val[1];
// test for MS Internet Explorer
}elseif(eregi("msie",$agent) && !eregi("opera",$agent)){
$val = explode(" ",stristr($agent,"msie"));
$bd['browser'] = $val[0];
$bd['version'] = $val[1];
// test for MS Pocket Internet Explorer
}elseif(eregi("mspie",$agent) || eregi('pocket', $agent)){
$val = explode(" ",stristr($agent,"mspie"));
$bd['browser'] = "MSPIE";
$bd['platform'] = "WindowsCE";
if (eregi("mspie", $agent))
$bd['version'] = $val[1];
else {
$val = explode("/",$agent);
$bd['version'] = $val[1];
}
// test for Galeon
}elseif(eregi("galeon",$agent)){
$val = explode(" ",stristr($agent,"galeon"));
$val = explode("/",$val[0]);
$bd['browser'] = $val[0];
$bd['version'] = $val[1];
// test for Konqueror
}elseif(eregi("Konqueror",$agent)){
$val = explode(" ",stristr($agent,"Konqueror"));
$val = explode("/",$val[0]);
$bd['browser'] = $val[0];
$bd['version'] = $val[1];
// test for iCab
}elseif(eregi("icab",$agent)){
$val = explode(" ",stristr($agent,"icab"));
$bd['browser'] = $val[0];
$bd['version'] = $val[1];
// test for OmniWeb
}elseif(eregi("omniweb",$agent)){
$val = explode("/",stristr($agent,"omniweb"));
$bd['browser'] = $val[0];
$bd['version'] = $val[1];
// test for Phoenix
}elseif(eregi("Phoenix", $agent)){
$bd['browser'] = "Phoenix";
$val = explode("/", stristr($agent,"Phoenix/"));
$bd['version'] = $val[1];
// test for Firebird
}elseif(eregi("firebird", $agent)){
$bd['browser']="Firebird";
$val = stristr($agent, "Firebird");
$val = explode("/",$val);
$bd['version'] = $val[1];
// test for Firefox
}elseif(eregi("Firefox", $agent)){
$bd['browser']="Firefox";
$val = stristr($agent, "Firefox");
$val = explode("/",$val);
$bd['version'] = $val[1];
// test for Mozilla Alpha/Beta Versions
}elseif(eregi("mozilla",$agent) &&
eregi("rv:[0-9].[0-9][a-b]",$agent) && !eregi("netscape",$agent)){
$bd['browser'] = "Mozilla";
$val = explode(" ",stristr($agent,"rv:"));
eregi("rv:[0-9].[0-9][a-b]",$agent,$val);
$bd['version'] = str_replace("rv:","",$val[0]);
// test for Mozilla Stable Versions
}elseif(eregi("mozilla",$agent) &&
eregi("rv:[0-9]\.[0-9]",$agent) && !eregi("netscape",$agent)){
$bd['browser'] = "Mozilla";
$val = explode(" ",stristr($agent,"rv:"));
eregi("rv:[0-9]\.[0-9]\.[0-9]",$agent,$val);
$bd['version'] = str_replace("rv:","",$val[0]);
// test for Lynx & Amaya
}elseif(eregi("libwww", $agent)){
if (eregi("amaya", $agent)){
$val = explode("/",stristr($agent,"amaya"));
$bd['browser'] = "Amaya";
$val = explode(" ", $val[1]);
$bd['version'] = $val[0];
} else {
$val = explode("/",$agent);
$bd['browser'] = "Lynx";
$bd['version'] = $val[1];
}
// test for Safari
}elseif(eregi("safari", $agent)){
$bd['browser'] = "Safari";
$bd['version'] = "";
// remaining two tests are for Netscape
}elseif(eregi("netscape",$agent)){
$val = explode(" ",stristr($agent,"netscape"));
$val = explode("/",$val[0]);
$bd['browser'] = $val[0];
$bd['version'] = $val[1];
}elseif(eregi("mozilla",$agent) && !eregi("rv:[0-9]\.[0-9]\.[0-9]",$agent)){
$val = explode(" ",stristr($agent,"mozilla"));
$val = explode("/",$val[0]);
$bd['browser'] = "Netscape";
$bd['version'] = $val[1];
}
// clean up extraneous garbage that may be in the name
$bd['browser'] = ereg_replace("[^a-z,A-Z]", "", $bd['browser']);
// clean up extraneous garbage that may be in the version
$bd['version'] = ereg_replace("[^0-9,.,a-z,A-Z]", "", $bd['version']);
// check for AOL
if (eregi("AOL", $agent)){
$var = stristr($agent, "AOL");
$var = explode(" ", $var);
$bd['aol'] = ereg_replace("[^0-9,.,a-z,A-Z]", "", $var[1]);
}
// finally assign our properties
$this->Name = $bd['browser'];
$this->Version = $bd['version'];
$this->Platform = $bd['platform'];
$this->AOL = $bd['aol'];
}
}
Any database programmer will tell you that in high-traffic database-driven applications, a single badly-designed SQL query can significantly impact the overall performance of your application. Not only does such a query consume more database time than it ideally should, but it can have an exponential effect on the performance of other application components.
Optimizing query performance is as much a black art as a science, as heavily dependent on the developer's intuition as on hard statistical performance data. Fortunately, databases likes MySQL come with some tools to aid the process, and this article discusses three of them briefly: using indexes, analyzing queries with EXPLAIN, and adjusting MySQL's internal configuration.
MySQL allows you to index database tables, making it possible to quickly seek to records without performing a full table scan first and thus significantly speeding up query execution. You can have up to 16 indexes per table, and MySQL also supports multi-column indexes and full-text search indexes.
Adding an index to a table is as simple as calling the CREATE INDEX command and specifying the field(s) to index. Listing A shows you an example:
mysql> CREATE INDEX idx_username ON users(username);
Query OK, 1 row affected (0.15 sec)
Records: 1 Duplicates: 0 Warnings: 0
Here, indexing the username field of the users table ensures that SELECT queries which reference this field in their WHERE or HAVING clause will run a little faster than in the pre-indexed state. You can check that the index was created (Listing B) with the SHOW INDEX command:
mysql> SHOW INDEX FROM users;
--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| users | 1 | idx_username | 1 | username | A | NULL | NULL | NULL | YES | BTREE | |
--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
1 row in set (0.00 sec)
It's important to note that indexes are a double-edged sword. Indexing every field of a table is usually unnecessary, and is quite likely to slow things down significantly when inserting or updating data because of the additional work MySQL has to do to rebuild the index each time. On the other hand, avoiding indexes altogether isn't such a great idea either, because while this will speed up INSERTs, it will cause SELECT operations to slow down. There is thus always a trade-off to be made, and it's wise to consider what the primary function of the table will be (data retrieval or data edit) when designing the indexing system.
When analyzing query performance, it's also useful to consider the EXPLAIN keyword. This keyword, when placed in front of a SELECT query, describes how MySQL intends to execute the query and the number of rows it will need to process to successfully deliver a result set. To illustrate, consider the following simple example (Listing C):
mysql> EXPLAIN SELECT city.name, city.district FROM city, country WHERE city.countrycode = country.code AND country.code = 'IND';
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+
| 1 | SIMPLE | country | const | PRIMARY | PRIMARY | 3 | const | 1 | Using index |
| 1 | SIMPLE | city | ALL | NULL | NULL | NULL | NULL | 4079 | Using where |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+
2 rows in set (0.00 sec)
Here, the query is structured as a join between two tables and the EXPLAIN keyword describes how MySQL will process the join. It should be clear the current design will require MySQL to process only one record in the country table (which is indexed) but all 4079 records in the city table (which isn't). This then suggests scope for improvement using other optimization tricks - for example, adding an index to the city table as follows (Listing D):
mysql> CREATE INDEX idx_ccode ON city(countrycode);
Query OK, 4079 rows affected (0.15 sec)
Records: 4079 Duplicates: 0 Warnings: 0
And now, when you re-run the query with EXPLAIN, you'll see a noticeable improvement (Listing E):
mysql> EXPLAIN SELECT city.name, city.district FROM city, country WHERE city.countrycode = country.code AND country.code = 'IND';
+----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+
| 1 | SIMPLE | country | const | PRIMARY | PRIMARY | 3 | const | 1 | Using index |
| 1 | SIMPLE | city | ref | idx_ccode | idx_ccode | 3 | const | 333 | Using where |
+----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+
2 rows in set (0.01 sec)
As this illustrates, MySQL now only needs to scan 333 records in the city table to produce a result set -- a reduction of almost 90 percent! Naturally, this translates into faster query execution time and more efficient usage of database resources.
MySQL is so open that it's fairly easy to further fine-tune its default settings to obtain greater performance and stability. Some of the key variables that should be optimized are listed below.
The previous discussion should give you some insight into three tools you can use to analyze and optimize your SQL queries, and help you squeeze better performance out of your application. Go on and try them out -- and happy optimizing!
| |||||||
| ------------------------------------------------------ Copyright 2002-2008 hi5 Networks, Inc. All rights reserved. 55 Second Street, Suite 300, San Francisco, CA 94105 Privacy Policy | Unsubscribe | Terms of Service |
<?php
function ae_nocache()
{
header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
}
<?php
ae_nocache();
// disable caching
// output some highly dynamic information
// time with microseconds
list($usec, $sec) = explode(" ", microtime());
echo $sec.'.'.$usec;
?>Not too long ago BollabathinChandrashkehar sent you an invite to join the
Scour search community and your invite is still open!
The Scour search engine is shaped by a community of users just like you,
and your contributions are what make it a success!
Why use Scour?
1. Get Yahoo, Google and MSN results in one search
2. Vote on result relevancy
3. Read user comments
4. Get paid for searching!
Create your profile at http://scour.com/invite/chandra4u/r/ and enjoy
searching the web through your favorite search engines. With time, you'll
get paid like these loyal users: http://www.scour.com/leaderboard page.
Come and be part of the largest Social Search community and help make the
results better!
See you soon,
The Scour Team
www.scour.com
This message was sent to you as a friend referral to join scour.com, please
feel free to review our http://scour.com/privacy page and our
http://scour.com/communityguidelines/antispam page.
If you prefer not to receive invitations from ANY scour members,
please click here - http://www.scour.com/unsub/e/Y2hhbmRyYTE3MDYuZGV2ZWxvcGVyQGJsb2dnZXIuY29t
-OR-
Write to us at:
Scour, Inc., 15303 Ventura Blvd. Suite 860, Sherman Oaks, CA 91403, USA.
campaignid: scour200810280002
One of the great things about MySQL is the superior innovation model that's used to deliver database server software. Rather than relying solely on internal engineers who create and maintain a piece of software (as in a traditional software company), MySQL partners with the millions of active users across the world who take advantage of the open source model and daily extend the MySQL server to do new and pioneering things. These innovations can then be submitted to MySQL AB, tested, validated, and rolled into the database server so everyone can benefit from the creativity of the very active MySQL community.
An example of this model in action is the recent release of a new SQL diagnostic facility that assists in the debugging and analysis of running SQL - the SQL Profiler. The new profiler became available in the 5.0.37 version of the MySQL Community Server and was created and submitted by Jeremy Cole of Proven Scaling (http://www.provenscaling.com/).
Let's take a look at this new diagnostic utility Jeremy developed and see how it can help you create high-performing SQL code as well as assist in troubleshooting existing queries that aren't providing the response times you'd like.
When it comes to overall performance, it's important to remember that the #1 contributor is always a good database design. The second highest contributor to performance is well-tuned SQL code. Some try and switch the two in priority, but this is a mistake because a bad design has the potential to simply drown even the best-tuned SQL code (e.g. you can't get index access in your SQL queries if the physical index design is poorly done). But make no mistake - bad SQL code that's introduced into an otherwise well-running database can make a real train wreck of things.
So how do you go about analyzing database performance? There are three forms of performance analysis that are used to troubleshoot and tune database systems:
Of the three, bottleneck analysis is the most efficient approach in terms of fast problem resolution. By determining where the server, a user connection, or set of SQL code is spending its time, you can then work to eliminate the discovered blockages, increase throughput, and reduce overall response times. Unfortunately, this hasn't always been easy in MySQL because the server hasn't traditionally exposed the type of wait-based and resource statistics to quickly uncover bottlenecks.
But a better day has come along in MySQL 5.0.37 with the inclusion of the SQL Profiling utility. This interactive diagnostic aid allows a developer or DBA to gain insight into where a set of SQL code spends its time and the resources it is using. The best way to see the power of this new utility is to walk through some examples of how it's used and see the clear benefits it supplies, so let's do just that.
The SQL Profiler is built into the database server and can be dynamically enabled/disabled via the MySQL client utility. To begin profiling one or more SQL queries, simply issue the following command:
mysql> set profiling=1;
Query OK, 0 rows affected (0.00 sec)
Two things happen once you issue this command. First, any query you issue from this point on will be traced by the server with various performance diagnostics being created and attached to each distinct query. Second, a memory table named profiling is created in the INFORMATION_SCHEMA database for your particular session (not viewable by any other MySQL session) that stores all the SQL diagnostic results. This table remains persistent until you disconnect from MySQL at which point it is destroyed.
Now, simply execute a SQL query:
mysql> select count(*) from client where broker_id=2;
+----------+
| count(*) |
+----------+
| 200 |
+----------+
1 row in set (0.00 sec)
Once the query completes, you can issue the following command to view the SQL profiles that have currently been stored for you:
mysql> show profiles;
+----------+------------+-----------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-----------------------------------------------+
| 0 | 0.00007300 | set profiling=1 |
| 1 | 0.00044700 | select count(*) from client where broker_id=2 |
+----------+------------+-----------------------------------------------+
2 rows in set (0.00 sec)
You get a quick summary of all your captured SQL plus the total duration that the query took to complete. To get the same diagnostic info, you can also query the memory table that holds your statistical information:
mysql> select sum(duration) from information_schema.profiling where query_id=1;
+---------------+
| sum(duration) |
+---------------+
| 0.000447 |
+---------------+
1 row in set (0.00 sec)
I'll show you why it's good to be able to query the memory-based profiling table later in this article, but for now, let's concentrate on other SHOW commands that you can use to get more detailed diagnostic info about one or more queries that you've profiled. The most basic command is one that lists the steps a profiled query went through to satisfy your SQL request, along with each step's time:
mysql> show profile for query 1;
+--------------------+------------+
| Status | Duration |
+--------------------+------------+
| (initialization) | 0.00006300 |
| Opening tables | 0.00001400 |
| System lock | 0.00000600 |
| Table lock | 0.00001000 |
| init | 0.00002200 |
| optimizing | 0.00001100 |
| statistics | 0.00009300 |
| preparing | 0.00001700 |
| executing | 0.00000700 |
| Sending data | 0.00016800 |
| end | 0.00000700 |
| query end | 0.00000500 |
| freeing items | 0.00001200 |
| closing tables | 0.00000800 |
| logging slow query | 0.00000400 |
+--------------------+------------+
15 rows in set (0.00 sec)
You can also just issue SHOW PROFILE and exclude the identification of a specific profile number to see the very last profile you created.
Regardless of how you obtain the output, you can see this data is extremely valuable in that it allows you to see where your query spends its time during execution. This is done for all types of queries, and not just SELECT statements as this example shows:
mysql> alter table t engine=myisam;
Query OK, 112050 rows affected (0.64 sec)
Records: 112050 Duplicates: 0 Warnings: 0
mysql> show profiles;
+----------+------------+-----------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-----------------------------------------------+
| 0 | 0.00007300 | set profiling=1 |
| 1 | 0.00044700 | select count(*) from client where broker_id=2 |
| 2 | 0.00003400 | set profiling=0 |
| 3 | 0.00007400 | set profiling=1 |
| 4 | 0.63789700 | alter table t engine=myisam |
| 5 | 0.00004000 | set profiling=0 |
+----------+------------+-----------------------------------------------+
6 rows in set (0.00 sec)
mysql> show profile for query 4;
+----------------------+------------+
| Status | Duration |
+----------------------+------------+
| (initialization) | 0.00002900 |
| checking permissions | 0.00000800 |
| init | 0.00004000 |
| Opening table | 0.00009400 |
| System lock | 0.00000500 |
| Table lock | 0.00000700 |
| setup | 0.00004200 |
| creating table | 0.00195800 |
| After create | 0.00010900 |
| copy to tmp table | 0.52264500 |
| rename result table | 0.11289400 |
| end | 0.00004600 |
| query end | 0.00000700 |
| freeing items | 0.00001300 |
+----------------------+------------+
14 rows in set (0.00 sec)
So as you can see in the above profile, the ALTER TABLE statement spends the bulk of its time in the temporary table copy step. Armed with this type of information, you have more insight into the hoops your query is jumping through from start to finish, and therefore, you can then work to tune your queries to help eliminate any identified bottlenecks.
There's more information than just duration that you can get from your profiles - for example, CPU usage (which, unfortunately, is not available on all platforms; the below comes from Linux):
mysql> show profile cpu for query 4;
+----------------------+------------+------------+------------+
| Status | Duration | CPU_user | CPU_system |
+----------------------+------------+------------+------------+
| (initialization) | 0.00002900 | 0.00000000 | 0.00000000 |
| checking permissions | 0.00000800 | 0.00000000 | 0.00000000 |
| init | 0.00004000 | 0.00000000 | 0.00000000 |
| Opening table | 0.00009400 | 0.00100000 | 0.00000000 |
| System lock | 0.00000500 | 0.00000000 | 0.00000000 |
| Table lock | 0.00000700 | 0.00000000 | 0.00000000 |
| setup | 0.00004200 | 0.00000000 | 0.00000000 |
| creating table | 0.00195800 | 0.00000000 | 0.00100000 |
| After create | 0.00010900 | 0.00000000 | 0.00000000 |
| copy to tmp table | 0.52264500 | 0.55591600 | 0.04199300 |
| rename result table | 0.11289400 | 0.00199900 | 0.00000000 |
| end | 0.00004600 | 0.00000000 | 0.00000000 |
| query end | 0.00000700 | 0.00000000 | 0.00000000 |
| freeing items | 0.00001300 | 0.00000000 | 0.00000000 |
+----------------------+------------+------------+------------+
14 rows in set (0.00 sec)
Other parameters that can be passed to the SHOW PROFILE command include:
Let's take a look at a quick example of how the new profiler can be a help to tune an inefficient query. I don't know about you, but I've always been just so-so at being able to really use EXPLAIN's to troubleshoot queries. But the new profiler makes things pretty nice and easy.
I have a MySQL database that's used to track investment activity for a small brokerage house. There's a view in the database that's used to get a quick report of client accounts over a million dollars:
mysql> select * from v_client_portfolio_high;
+-----------+-------------------+------------------+-----------------+
| client_id | client_first_name | client_last_name | portfolio_value |
+-----------+-------------------+------------------+-----------------+
| 5 | ABNER | ROSSELLETT | 1252115.50 |
| 500 | CANDICE | BARTLETT | 1384877.50 |
+-----------+-------------------+------------------+-----------------+
2 rows in set (3.73 sec)
Now a query running under four seconds isn't necessarily a bad thing, but I wonder if things could be made a little bit better. So let's profile the view and see what we can discover:
mysql> set profiling=1;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from v_client_portfolio_high;
+-----------+-------------------+------------------+-----------------+
| client_id | client_first_name | client_last_name | portfolio_value |
+-----------+-------------------+------------------+-----------------+
| 5 | ABNER | ROSSELLETT | 1252115.50 |
| 500 | CANDICE | BARTLETT | 1384877.50 |
+-----------+-------------------+------------------+-----------------+
2 rows in set (4.01 sec)
mysql> set profiling=0;
Query OK, 0 rows affected (0.00 sec)
mysql> show profiles;
+----------+------------+-----------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-----------------------------------------------+
| 0 | 0.00007300 | set profiling=1 |
| 1 | 0.00044700 | select count(*) from client where broker_id=2 |
| 2 | 0.00003400 | set profiling=0 |
| 3 | 0.00007400 | set profiling=1 |
| 4 | 0.63789700 | alter table t engine=myisam |
| 5 | 0.00004000 | set profiling=0 |
| 6 | 0.00007600 | set profiling=1 |
| 7 | 4.01965600 | select * from v_client_portfolio_high |
| 8 | 0.00003500 | set profiling=0 |
+----------+------------+-----------------------------------------------+
Now at first, I'm tempted to issue a SHOW PROFILE for query 7, which is my view query, but instead let's see just how many lines of diagnostic data the profiler has collected for me:
mysql> select count(*) from information_schema.profiling where query_id=7;
+----------+
| count(*) |
+----------+
| 74734 |
+----------+
Hello! The profiler generated over 74,000 lines of output for me, which might be hard to wade through using the normal SHOW PROFILE command (even though a LIMIT option is provided). Instead, let's use a SQL query against the profiling table to see what our query did:
mysql> select min(seq) seq,state,count(*) numb_ops,
-> round(sum(duration),5) sum_dur, round(avg(duration),5) avg_dur,
-> round(sum(cpu_user),5) sum_cpu, round(avg(cpu_user),5) avg_cpu
-> from information_schema.profiling
-> where query_id = 7
-> group by state
-> order by seq;
+-------+----------------------+----------+---------+---------+---------+---------+
| seq | state | numb_ops | sum_dur | avg_dur | sum_cpu | avg_cpu |
+-------+----------------------+----------+---------+---------+---------+---------+
| 0 | (initialization) | 1 | 0.00004 | 0.00004 | 0.00000 | 0.00000 |
| 1 | Opening tables | 1 | 0.00023 | 0.00023 | 0.00000 | 0.00000 |
| 2 | System lock | 1 | 0.00001 | 0.00001 | 0.00000 | 0.00000 |
| 3 | Table lock | 1 | 0.00001 | 0.00001 | 0.00000 | 0.00000 |
| 4 | checking permissions | 1 | 0.00010 | 0.00010 | 0.00000 | 0.00000 |
| 5 | optimizing | 4 | 0.00004 | 0.00001 | 0.00000 | 0.00000 |
| 6 | statistics | 4 | 0.00007 | 0.00002 | 0.00100 | 0.00025 |
| 7 | preparing | 4 | 0.00005 | 0.00001 | 0.00000 | 0.00000 |
| 8 | Creating tmp table | 1 | 0.00003 | 0.00003 | 0.00000 | 0.00000 |
| 9 | executing | 37352 | 0.16631 | 0.00000 | 0.05899 | 0.00000 |
| 10 | Copying to tmp table | 1 | 0.00006 | 0.00006 | 0.00000 | 0.00000 |
| 15 | Sending data | 37353 | 3.85151 | 0.00010 | 3.72943 | 0.00010 |
| 74717 | Sorting result | 1 | 0.00112 | 0.00112 | 0.00100 | 0.00100 |
| 74719 | removing tmp table | 2 | 0.00003 | 0.00001 | 0.00000 | 0.00000 |
| 74721 | init | 1 | 0.00002 | 0.00002 | 0.00000 | 0.00000 |
| 74727 | end | 1 | 0.00001 | 0.00001 | 0.00000 | 0.00000 |
| 74728 | query end | 1 | 0.00000 | 0.00000 | 0.00000 | 0.00000 |
| 74729 | freeing items | 1 | 0.00002 | 0.00002 | 0.00000 | 0.00000 |
| 74730 | closing tables | 2 | 0.00001 | 0.00001 | 0.00000 | 0.00000 |
| 74733 | logging slow query | 1 | 0.00000 | 0.00000 | 0.00000 | 0.00000 |
+-------+----------------------+----------+---------+---------+---------+---------+
Looking at the diagnostics above, I can see that my view query spends the bulk of its time in the Sending data step, with that step and the executing step experiencing over 37,000 operations. Why would this be the case? Let's take a look at the underlying view definition and see what the actual query looks like:
create view v_client_portfolio_high
(
client_id,
client_first_name,
client_last_name,
portfolio_value
)
as
select b.client_id,
b.client_first_name,
b.client_last_name,
(select sum(number_of_units * price)
from client_transaction c
where c.action = 'buy' and
c.client_id = b.client_id) -
(select sum(number_of_units * price)
from client_transaction d
where d.action = 'sell' and
d.client_id = b.client_id) portfolio_value
from client_transaction a,
client b
where a.client_id = b.client_id
group by b.client_id,
b.client_first_name,
b.client_last_name
having portfolio_value > 1000000
The view does some normal column grabs from the underlying base tables, but then uses some inline views to calculate a client's overall portfolio value. The inline views/subselects are obviously what's causing the large number of data sends and executions. Let's eliminate just one of the subselects by pulling it up into the main query and if that makes a difference. We'll drop and recreate the view (with a little clean up on NULL values that may affect the computed outcome), profile the new view's performance, and then examine the diagnostic output:
mysql> drop view v_client_portfolio_high;
Query OK, 0 rows affected (0.00 sec)
mysql> create view v_client_portfolio_high
-> (
-> client_id,
-> client_first_name,
-> client_last_name,
-> portfolio_value
-> )
-> as
-> select b.client_id,
-> b.client_first_name,
-> b.client_last_name,
-> sum(number_of_units * price) -
-> case
-> (select sum(number_of_units * price)
-> from client_transaction d
-> where d.action = 'sell' and
-> d.client_id = b.client_id)
-> when NULL then 0
-> else
-> (select sum(number_of_units * price)
-> from client_transaction d
-> where d.action = 'sell' and
-> d.client_id = b.client_id)
-> end portfolio_value
-> from client_transaction a,
-> client b
-> where a.client_id = b.client_id and
-> action = 'buy'
-> group by b.client_id,
-> b.client_first_name,
-> b.client_last_name
-> having portfolio_value > 1000000;
Query OK, 0 rows affected (0.00 sec)
mysql> set profiling=1;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from v_client_portfolio_high;
+-----------+-------------------+------------------+-----------------+
| client_id | client_first_name | client_last_name | portfolio_value |
+-----------+-------------------+------------------+-----------------+
| 5 | ABNER | ROSSELLETT | 1252115.50 |
| 500 | CANDICE | BARTLETT | 1384877.50 |
+-----------+-------------------+------------------+-----------------+
2 rows in set (0.47 sec)
mysql> set profiling=0;
Query OK, 0 rows affected (0.00 sec)
mysql> show profiles;
+----------+------------+-----------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-----------------------------------------------+
| 0 | 0.00007300 | set profiling=1 |
| 1 | 0.00044700 | select count(*) from client where broker_id=2 |
| 2 | 0.00003400 | set profiling=0 |
| 3 | 0.00007400 | set profiling=1 |
| 4 | 0.63789700 | alter table t engine=myisam |
| 5 | 0.00004000 | set profiling=0 |
| 6 | 0.00007600 | set profiling=1 |
| 7 | 4.01965600 | select * from v_client_portfolio_high |
| 8 | 0.00003500 | set profiling=0 |
| 9 | 0.00007500 | set profiling=1 |
| 10 | 0.45292700 | select * from v_client_portfolio_high |
| 11 | 0.00003800 | set profiling=0 |
+----------+------------+-----------------------------------------------+
12 rows in set (0.00 sec)
mysql> select min(seq) seq,state,count(*) numb_ops,
-> round(sum(duration),5) sum_dur, round(avg(duration),5) avg_dur,
-> round(sum(cpu_user),5) sum_cpu, round(avg(cpu_user),5) avg_cpu
-> from information_schema.profiling
-> where query_id = 10
-> group by state
-> order by seq;
+-------+----------------------+----------+---------+---------+---------+---------+
| seq | state | numb_ops | sum_dur | avg_dur | sum_cpu | avg_cpu |
+-------+----------------------+----------+---------+---------+---------+---------+
| 0 | (initialization) | 1 | 0.00004 | 0.00004 | 0.00000 | 0.00000 |
| 1 | Opening tables | 1 | 0.00024 | 0.00024 | 0.00000 | 0.00000 |
| 2 | System lock | 1 | 0.00001 | 0.00001 | 0.00000 | 0.00000 |
| 3 | Table lock | 1 | 0.00001 | 0.00001 | 0.00000 | 0.00000 |
| 4 | checking permissions | 1 | 0.00012 | 0.00012 | 0.00100 | 0.00100 |
| 5 | optimizing | 4 | 0.00005 | 0.00001 | 0.00000 | 0.00000 |
| 6 | statistics | 4 | 0.00007 | 0.00002 | 0.00000 | 0.00000 |
| 7 | preparing | 4 | 0.00005 | 0.00001 | 0.00000 | 0.00000 |
| 8 | Creating tmp table | 1 | 0.00003 | 0.00003 | 0.00000 | 0.00000 |
| 9 | executing | 11194 | 0.04983 | 0.00000 | 0.01800 | 0.00000 |
| 10 | Copying to tmp table | 1 | 0.00008 | 0.00008 | 0.00000 | 0.00000 |
| 15 | Sending data | 11195 | 0.39853 | 0.00004 | 0.36794 | 0.00003 |
| 22401 | Sorting result | 1 | 0.00375 | 0.00375 | 0.00400 | 0.00400 |
| 22403 | removing tmp table | 2 | 0.00005 | 0.00002 | 0.00000 | 0.00000 |
| 22405 | init | 1 | 0.00002 | 0.00002 | 0.00000 | 0.00000 |
| 22411 | end | 1 | 0.00001 | 0.00001 | 0.00000 | 0.00000 |
| 22412 | query end | 1 | 0.00000 | 0.00000 | 0.00000 | 0.00000 |
| 22413 | freeing items | 1 | 0.00002 | 0.00002 | 0.00000 | 0.00000 |
| 22414 | closing tables | 2 | 0.00001 | 0.00001 | 0.00000 | 0.00000 |
| 22417 | logging slow query | 1 | 0.00000 | 0.00000 | 0.00000 | 0.00000 |
+-------+----------------------+----------+---------+---------+---------+---------+
20 rows in set (0.44 sec)
Much better! Although more tuning on the view can likely be done, this simple change has knocked the Sending data and the executing step counts down by over two-thirds, with the end result being an 88% reduction in overall response time. The profiler was very useful in this case as this particular query shows that even though an individual step in the SQL execution process may be handled very quickly (the average duration column in the above query), having that same step executed over and over again can put a major dent in total query performance.
Here are some other things to keep in mind when using the new SQL profiler:
Profiling is initially turned off for each session.
By default, you can store 15 different query profiles for your session. You can increase this up to 100 by setting the profiling_history_size session variable. Certain diagnostics rely on operating system support for the getrusage() system call, so you may see NULL values for some statistics if you're on a platform that doesn't support this function.
There were a few bugs in the initial release of the profiler. The first centered around a problem that developed if you issued a SHOW PROFILES command before enabling profiling. Another concerned duration statistics that were not accurately paired up for each SQL execution step. All these have been fixed now and will be in the next Community server source drop and binary.
For more information on the SQL profiler, you can review the documentation found in the MySQL 5.0 manual at: http://dev.mysql.com/doc/refman/5.0/en/show-profiles.html.
The new SQL profiler is a nice addition to the DBA's and developer's toolbelt and is a great example of the vibrant MySQL Community (in this case, Jeremy Cole) in action. I can't wait to see what they come up with next!
Regards
R. Satish Kumar
#macro( select $name $displayname $choicelist )
<SELECT name=$name>
<option value="">$displayname</option>
#foreach( $choice in $choicelist )
<option value=$choice>$choice</option>
Directives are VTL's other major part. Like references, they freely mix with other non-VTL content in templates. The directives in VTL are:
#set()
#if()
#else
#elseif()
One of Velocity's strengths is that it strongly enforces a separation of functional responsibility within the application. It does this by limiting template access to objects that the application code specifically makes available. This means that designers can focus exclusively on the data presentation (the view), and the application programmer can focus on the application control (the controller) and the business logic and data management (the model) in Model-View-Controller (MVC) development. MVC is a well-accepted development pattern that simplifies both development and ongoing maintenance of sophisticated applications.
Velocity is successfully used in:
Velocity is most commonly used as a rendering engine for Java servlet-based Web application development, in place of or in conjunction with JSPs and other rendering technologies. Besides the easy, maintainable template syntax, Velocity is used in Web development because its template language can manipulate and present the data, not create data. This discourages programming within the templates. This is a good thing; it keeps your Java code's business and application logic where they belong.
Velocity is well suited to J2EE (Java 2 Platform, Enterprise Edition) Web development because the platform accommodates output technologies other than JSP. While JSP is included in the J2EE specification, J2EE doesn't require its use.
You use the same general process to create a Velocity-based application as you would any application. Let's consider a more interesting example than the Hello World application above. Suppose you operate a pet store and wish to generate an email blast to announce a sale. First, you must design the email and then develop the template and code based on that design.
You need to consider three elements for your design:
List, Map, or String) For this example, let's suppose you decide on three pets for sale, each with a different advertised price. You decide to use a map to associate each pet name and its price, and then store all three maps in a list. You call this list petList, the pet name name, and the price as price in the map. Now that you have identified the relevant data, its representation, and naming criteria, you can write the code and the template's design.
Once you agree on data specifics, Velocity lets you write the code and design the template in parallel. The designer integrates the data into the nondata presentation content (like images, text, and so on) in the template. In this case, we simply write in the email body:
$petList.size() Pets on Sale!
We are proud to offer these fine pets
at these amazing prices. This month only,
choose from:
#foreach( $pet in $petList )
$pet.name for only $pet.price
By Geir Magnusson Jr., JavaWorld.com, 12/28/01
Velocity is an open source templating tool developed by an international volunteer community and hosted by the Apache Software Foundation's Jakarta Project. At the Jakarta Velocity Project Website, where you can download the freely available source code, a thriving and growing community of users is ready to answer questions and offer solutions to common templating problems. Velocity was inspired by the pioneering WebMacro project, a work for which we in the Velocity community are grateful.In this article, I present a short primer on the Velocity Template Engine and its template language, Velocity Template Language (VTL). I also demonstrate how to use Velocity through several examples.
No explanation of a programming-related subject would be complete without a Hello World example. Any application using Velocity requires two parts. The first is the template, which in this example is a file called helloworld.vm:
Hello $name! Welcome to Velocity!
The second is a corresponding Java program called HelloWorld.java:
import java.io.StringWriter;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
public class HelloWorld
{
public static void main( String[] args )
throws Exception
{
/* first, get and initialize an engine */
VelocityEngine ve = new VelocityEngine();
ve.init();
/* next, get the Template */
Template t = ve.getTemplate( "helloworld.vm" );
/* create a context and add data */
VelocityContext context = new VelocityContext();
context.put("name", "World");
/* now render the template into a StringWriter */
StringWriter writer = new StringWriter();
t.merge( context, writer );
/* show the World */
System.out.println( writer.toString() );
}
}
Now, when you compile and run this program, you will see the output:
Hello World! Welcome to Velocity!
This is a trivial example, but it contains the crucial pieces to give you an idea of what Velocity templating is all about.
Designed as an easy-to-use general templating tool, Velocity is useful in any Java application area that requires data formatting and presentation. You should use Velocity for the following reasons:
The last point is important -- it means that you can reuse your existing classes. So, objects you want to use in your templates don't need to be structured in a certain way, like JavaBeans, or implement special I/O or lifecycle modes, such as JSP (JavaServer Pages) taglibs. The only requirement is that methods are public. You will see more of this when we cover the template language in detail.
Development cycle for java code
===============================
[development start]
|
V
maven turbine:setup - generate skeleton
|
V
+-----> [application development]
| |
| V
^ maven java:compile - compile code
| |
| V
+-<-- yes <--- Errors / Test failures?
| |
^ | no
| V
| optional: maven turbine:deploy - deploy to container
| (not needed in "inplace" mode)
| |
| V
^ [In-container testing]
| |
| V
+-<-- yes <--- Errors?
| |
^ | no
| V
+-<-- no <---- Ready to ship?
|
| yes
V
maven turbine:war - bind a war file
|
V
Ship application
Development cycle for SQL code
==============================
[development start]
|
V
maven turbine:setup - generate skeleton
|
V
maven torque:create-db - generate DB
|
V
+-----> [application development]
| |
| V
^ maven turbine:sql - generate SQL code
| |
| V
^ maven torque:insert-sql - put SQL in DB
| |
| V
+-<-- yes <--- Errors?
| |
^ | no
| V
+-<-- no <---- Ready to ship?
|
| yes
V
Ship files from target/sql directory
The MyEclipse Ajax Workbench™ is a special Eclipse workbench which provides MyEclipse Ajax tools in a single window. When a MyEclipse Ajax Web Browser is created or a JavaScript debug session is launched, the MyEclipse Ajax Workbench™ window is activated and the web page and information describing the web page is displayed in the browser and support views.
The MyEclipse Ajax Workbench™ consists of the following features:
The following figure depicts the typical layout of the MyEclipse Ajax Workbench™. The highlighted elements are described in further detail in subsequent sections of this document.
The MyEclipse Ajax Workbench™
The MyEclipse Ajax Perspective is a user customizable layout of user-interface views, editors, menus and toolbar actions. The perspective's default layout can be seen in the figure above. The MyEclipse Ajax Perspective is opened by default when the MyEclipse Ajax Workbench™ is created, but can be accessed via the perspective shortcut pulldown.
Perspective shortcut
The MyEclipse Ajax Workbench™ provides an integrated version of the Mozilla browser called the MyEclipse Ajax Web Browser which provides standard web browser capabilities as well as support for the all of the related Ajax views that are discussed in the Ajax Related Views section.
In addition, the MyEclipse Ajax Web Browser provides JavaScript debugging facilities. When a JavaScript debug session is launched the MyEclipse Ajax Workbench™ will open and the MyEclipse Ajax Web Browser will display the JavaScript application that is being debugged. The JavaScript scripts that are loaded will be displayed in the JavaScript Scripts Inspector.
The MyEclipse Ajax Web Browser provides standard web browser facilities as well as the DOM Selection tool which enables you to determine the DOM nodes which correspond with selected HTML elements in the browser.
MyEclipse Ajax Browser
The MyEclipse Ajax Web Browser also provides a source view page that displays the HTML source of the current page in the browser as shown.
Ajax Web Browser Source View
The easiest method for launching the Ajax Web Browser from the MyEclipse Ajax Perspective is to use the Launch MyEclipse Ajax Web Browser action the main toolbar (see the figure below). This action can be found in many of the MyEclipse development perspectives.
Launch Ajax Web Browser action
An alternative method for launching the Ajax Web Browser is from the New File Wizard in eclipse as depicted ( File->New->MyEclipse->Web->Ajax Web Browser).
Launching a new MyEclipse Ajax Web Browser from File->New
The Ajax Web Browser provides standard web browser actions including forward, back, open URL, refresh, and stop loading. In addition to the standard actions it provides two non-standard actions. The first, Clear browser cache, removes all saved data from the browser's cache. The second, the DOM selection action, allows you to select regions within the browser and have the corresponding DOM elements selected in the DOM inspector. This is an easy way to determine how changes in your document are affecting the structure of your document and vice versa.
Ajax Web Browser Actions
To use DOM selection, click the DOM selection button and then use Ctrl+Click in the browser as shown.
Using the DOM Selection Tool to quickly navigate the DOM
The MyEclipse Ajax Web Browser allows you to preview your web applications from within MyEclipse, however it's true power lies in the supporting views that surround it.
The MyEclipse Ajax Perspective includes all of these views by default. If you have closed a view and wish to re-open it you can access these views from the Ajax Perspective via the Window->Show View submenu as is depicted.
Opening Ajax Related Views via Window->Show View
The DOM Inspector displays a real-time view of the current browser's document object model (DOM). The DOM Inspector displays the DOM using a tree of document nodes and an attributes editor which displays detailed information for the selected node. In the figure below, the Ajax Web Browser has loaded the Google home page and the corresponding DOM is depicted by the DOM Inspector.
Notice that the DOM Inspector allows you to inspect the box model, DOM attributes, and computed styles of each node. The box model allows you to inspect how each node will be displayed, the DOM attributes allows you to inspect the HTML attributes of the selected node, and the computed style allows you to introspect the CSS style that was computed by the browser for the selected node.
As you select nodes in the DOM Inspector, the corresponding objects in the browser will temporarily flash to reveal their location.
DOM Inspector
Using the DOM Inspector you can dynamically change the attributes of some tags. In the next figure, the width and height attributes of the IMG node have been adjusted dramatically for effect using the Attributes Editor as shown.
Using the DOM Attributes Editor to dynamically change DOM element attributes
The DOM Inspector has a Search Filter capability that allows searching nodes by 3 different search criteria.
In the following, the Name filter has been activated and the search criteria is "DIV". Notice how only the DIV elements are shown in the DOM Inspector.
DOM Inspector Search
Each node in the DOM Inspector has several actions that can be performed on it through the context-menu. The figure below shows all of the DOM node related actions that are available for any node in the DOM Inspector.
DOM Node Actions
The DOM Source view displays the dynamic source for the element selected in the DOM Inspector View. This is useful if any Ajax routines in your application are modifying the DOM on the page because the DOM Source view allows you to see the dynamic source that is no longer available in the Browser source page.
There are several actions available on the DOM Source view that are used to interact with the corresponding DOM node. There is also a Source Status field that displays the current status of the DOM source with respect to the Node in the browser.
DOM Source view actions
The following figure illustrates the potential of the DOM Source View. If the example below, a chat application uses a DIV element to add new chat messages. In this figure, the chat DIV has been selected and in the DOM Source you can see the DIV element is initially empty.
Using the DOM Source to view dynamic DOM elements
In the next figure, a new chat message has appeared via an Ajax request and the DOM Source view indicates that there have been changes to this node in the DOM Source.
DOM Source status changes to show that selected element has changed
Now that the DOM Source has changed the "Refresh" action can be used to update the DOM Source with the latest version of the Node source as shown.
Refreshing the changes to the DOM Node
The DOM Watcher can monitor the events or changes that are associated with any selected or referenced node in the browser. In the figure below, a DIV element in the browser page has been selected and the "Start Watching" action has been used to monitor any events that fire off of that element.
DOM Watcher view starts watch on a DIV element
If any events fire from this DIV element, those events and their changes will be listed in the DOM Watcher. In this figure, the DIV element which was hidden has now been made visible through javascript and you can see the style attribute change.
DOM Watcher shows the attribute change to the element that is being watched
By default all events will be logged in the DOM Watcher. However, you can modify the list of events that are "watched" through the "Settings..." menu action as shown.
Settings for supported events in the DOM Watcher view
The JavaScript view allows evaluation of any DOM node as a JavaScript object. Simply right-click on any DOM node and choose "Evaluate Node" for it to be shown in the JavaScript view as shown.
Evaluation of DOM Node in JavaScript view
The JavaScript expression field can handle general evaluation of JavaScript code as shown.
General evaluation of JavaScript code
The CSS View shows extended information for elements that are selected in the DOM Inspector. The CSS View shows the following 4 types of extended CSS information:
CSS properties can be added or edited using the actions as shown.
CSS Styles
The Box Model for a particular element can be displayed in the CSS View as shown. Modification of the box model is possible by using the Navigation Controls.
Box Model in CSS View
The Ajax Request Monitor allows you to inspect the requests and responses your JavaScript application sends and receives. It displays each request/response pair in a table. Selecting an entry in this table displays the headers for each request/response. The body tab allows you to see the body of each request.
The Ajax Request Monitor
The JavaScript Console displays messages that the browser produces while loading pages and style sheets, as well as JavaScript warnings and errors. The view can be filtered to display only messages of a certain type.
The JavaScript Console displaying CSS warnings.
JavaScript errors and exceptions are also shown in the JavaScript Console as shown.
JavaScript error shown in JavaScript console
The JavaScript Scripts Inspector displays all of the scripts that are loaded during the rendering of a web page. In order for the scripts view to populate with scripts you must be running a JavaScript debug session. The easiest way to do this is to select the Instant-on JavaScript Debugging action located in the toolbar next to the New Ajax Web Browser action.
The JavaScript Scripts Inspector when no JavaScript Debug Session is active.
Once the JavaScript Scripts Inspector has been populated you can double click on a URL or function in the scripts view to open an editor to display the source of that URL or function. The editor opened will be read only, but it will allow you to set breakpoints and debug the JavaScript application.
For more information on JavaScript debugging in MyEclipse see the JavaScript Development and Debugging Tutorial.
The JavaScript Scripts Inspector displaying URLs and functions.
The MyEclipse JavaScript Editor provides advanced language specific editing features such as:
The JavaScript editor provides code-assist proposals for your current context whenever you press the Ctrl+Space key combination. Each proposal includes a small graphic indicator of whether the JavaScript proposal is supported by IE and Netscape/Mozilla/Firefox. If a browser compatibility indicator is grayed out then the proposal is not supported by that browser.
JavaScript content-assist example
Local JavaScript variables and functions are also made available in the code-assist proposals.
Local JavaScript Function completion
The JavaScript editor provides "as-you-type" syntax checking and shows syntax errors in multiple locations to make it easy to see where errors are in your JavaScript code.
"As-you-type" Syntax checking
Validation problems are indicated as warning markers in the JavaScript Editor, Problems view and in the Package Explorer view. To view problem details, in the JavaScript fly-over a warning marker in the left margin as shown.
Viewing JavaScript validation warnings
The outline view depicts a structured view of the functions and variables of a JavaScript Editor. The variables in the list may be filtered using the "Show Variables" action from the view's menubar.
Outline view with activated menu
Source Actions: Formatting/Quick Comment
The JavaScript editor can quickly format either highlighted sections or the entire JavaScript file. This action is available in the Source menu, editor Context-menu, or using the Ctrl+F shortcut.
Format action
To toggle on or off one or more single line comments select the region to comment and enter Ctrl+Shift+C .
The JavaScript editor has several source related preference pages that allow you configure different aspects of editing JavaScript.
JavaScript Preference page
The JavaScript Source page configures options for formatting source and content-assist. Validation options are also available.
JavaScript Source preference page
JavaScript styles preference page allows customization of syntax highlighting.
JavaScript Styles preference page
The JavaScript validator can be enabled/disabled by configuring the options in the main validation preference page.