1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is JavaScript Engine testing utilities.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corp.
19 * Portions created by the Initial Developer are Copyright (C) 2002
20 * the Initial Developer. All Rights Reserved.
23 * rogerl@netscape.com, pschwartau@netscape.com
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
42 * SUMMARY: Performance: Regexp performance degraded from 4.7
43 * See http://bugzilla.mozilla.org/show_bug.cgi?id=85721
45 * Adjust this testcase if necessary. The FAST constant defines
46 * an upper bound in milliseconds for any execution to take.
49 //-----------------------------------------------------------------------------
50 var BUGNUMBER = 85721;
51 var summary = 'Performance: execution of regular expression';
52 var FAST = 100; // execution should be 100 ms or less to pass the test
53 var MSG_FAST = 'Execution took less than ' + FAST + ' ms';
54 var MSG_SLOW = 'Execution took ';
62 printBugNumber(BUGNUMBER);
63 printStatus (summary);
66 function elapsedTime(startTime)
68 return new Date() - startTime;
72 function isThisFast(ms)
76 return MSG_SLOW + ms + MSG_MS;
82 * The first regexp. We'll test for performance (Section 1) and accuracy (Section 2).
84 str='<sql:connection id="conn1"> <sql:url>www.m.com</sql:url> <sql:driver>drive.class</sql:driver>\n<sql:userId>foo</sql:userId> <sql:password>goo</sql:password> </sql:connection>';
85 re = /<sql:connection id="([^\r\n]*?)">\s*<sql:url>\s*([^\r\n]*?)\s*<\/sql:url>\s*<sql:driver>\s*([^\r\n]*?)\s*<\/sql:driver>\s*(\s*<sql:userId>\s*([^\r\n]*?)\s*<\/sql:userId>\s*)?\s*(\s*<sql:password>\s*([^\r\n]*?)\s*<\/sql:password>\s*)?\s*<\/sql:connection>/;
86 expect = Array("<sql:connection id=\"conn1\"> <sql:url>www.m.com</sql:url> <sql:driver>drive.class</sql:driver>\n<sql:userId>foo</sql:userId> <sql:password>goo</sql:password> </sql:connection>","conn1","www.m.com","drive.class","<sql:userId>foo</sql:userId> ","foo","<sql:password>goo</sql:password> ","goo");
91 status = inSection(1);
92 var start = new Date();
93 var result = re.exec(str);
94 actual = elapsedTime(start);
95 reportCompare(isThisFast(FAST), isThisFast(actual), status);
100 status = inSection(2);
101 testRegExp([status], [re], [str], [result], [expect]);
106 * The second regexp (HUGE!). We'll test for performance (Section 3) and accuracy (Section 4).
107 * It comes from the O'Reilly book "Mastering Regular Expressions" by Jeffrey Friedl, Appendix B
110 //# Some things for avoiding backslashitis later on.
113 $space = '\040'; $tab = '\t';
114 $OpenBR = '\\['; $CloseBR = '\\]';
115 $OpenParen = '\\('; $CloseParen = '\\)';
116 $NonASCII = '\x80-\xff'; $ctrl = '\000-\037';
117 $CRlist = '\n\015'; //# note: this should really be only \015.
119 $qtext = '[^' + $esc + $NonASCII + $CRlist + '\"]'; // # for within "..."
120 $dtext = '[^' + $esc + $NonASCII + $CRlist + $OpenBR + $CloseBR + ']'; // # for within [...]
121 $quoted_pair = $esc + '[^' + $NonASCII + ']'; // # an escaped character
123 //##############################################################################
124 //# Items 22 and 23, comment.
125 //# Impossible to do properly with a regex, I make do by allowing at most one level of nesting.
126 $ctext = '[^' + $esc + $NonASCII + $CRlist + '()]';
128 //# $Cnested matches one non-nested comment.
129 //# It is unrolled, with normal of $ctext, special of $quoted_pair.
132 $ctext + '*' + // # normal*
133 '(?:' + $quoted_pair + $ctext + '*)*' + // # (special normal*)*
137 //# $comment allows one level of nested parentheses
138 //# It is unrolled, with normal of $ctext, special of ($quoted_pair|$Cnested)
141 $ctext + '*' + // # normal*
143 '(?:' + $quoted_pair + '|' + $Cnested + ')' + // # special
144 $ctext + '*' + // # normal*
149 //##############################################################################
150 //# $X is optional whitespace/comments.
152 '[' + $space + $tab + ']*' + // # Nab whitespace.
153 '(?:' + $comment + '[' + $space + $tab + ']*)*'; // # If comment found, allow more spaces.
157 $atom_char = '[^(' + $space + '<>\@,;:\".' + $esc + $OpenBR + $CloseBR + $ctrl + $NonASCII + ']';
159 $atom_char + '+' + // # some number of atom characters...
160 '(?!' + $atom_char + ')'; // # ..not followed by something that could be part of an atom
162 // # Item 11: doublequoted string, unrolled.
165 $qtext + '*' + // # normal
166 '(?:' + $quoted_pair + $qtext + '*)*' + // # ( special normal* )*
169 //# Item 7: word is an atom or quoted string
174 $quoted_str + // # Quoted string
177 //# Item 12: domain-ref is just an atom
180 //# Item 13: domain-literal is like a quoted string, but [...] instead of "..."
183 '(?:' + $dtext + '|' + $quoted_pair + ')*' + // # stuff
186 // # Item 9: sub-domain is a domain-ref or domain-literal
193 $X; // # optional trailing comments
195 // # Item 6: domain is a list of subdomains separated by dots.
199 $Period + $X + $sub_domain +
202 //# Item 8: a route. A bunch of "@ $domain" separated by commas, followed by a colon.
204 '\@' + $X + $domain +
205 '(?:,' + $X + '\@' + $X + $domain + ')*' + // # additional domains
207 $X; // # optional trailing comments
209 //# Item 6: local-part is a bunch of $word separated by periods
213 $Period + $X + $word + $X + // # additional words
216 // # Item 2: addr-spec is local@domain
218 $local_part + '\@' + $X + $domain;
220 //# Item 4: route-addr is <route? addr-spec>
223 '(?:' + $route + ')?' + // # optional route
224 $addr_spec + // # address spec
227 //# Item 3: phrase........
228 $phrase_ctrl = '\000-\010\012-\037'; // # like ctrl, but without tab
230 //# Like atom-char, but without listing space, and uses phrase_ctrl.
231 //# Since the class is negated, this matches the same as atom-char plus space and tab
233 '[^()<>\@,;:\".' + $esc + $OpenBR + $CloseBR + $NonASCII + $phrase_ctrl + ']';
235 // # We've worked it so that $word, $comment, and $quoted_str to not consume trailing $X
236 // # because we take care of it manually.
238 $word + // # leading word
239 $phrase_char + '*' + // # "normal" atoms and/or spaces
241 '(?:' + $comment + '|' + $quoted_str + ')' + // # "special" comment or quoted string
242 $phrase_char + '*' + // # more "normal"
245 // ## Item #1: mailbox is an addr_spec or a phrase/route_addr
247 $X + // # optional leading comment
249 $phrase + $route_addr + // # name and address
251 $addr_spec + // # address
255 //###########################################################################
258 re = new RegExp($mailbox, "g");
259 str = 'Jeffy<"That Tall Guy"@ora.com (this address is no longer active)>';
260 expect = Array('Jeffy<"That Tall Guy"@ora.com (this address is no longer active)>');
263 * Check performance -
265 status = inSection(3);
266 var start = new Date();
267 var result = re.exec(str);
268 actual = elapsedTime(start);
269 reportCompare(isThisFast(FAST), isThisFast(actual), status);
274 status = inSection(4);
275 testRegExp([status], [re], [str], [result], [expect]);