Return-Path: X-Original-To: apmail-incubator-flex-dev-archive@minotaur.apache.org Delivered-To: apmail-incubator-flex-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 8545DE1DA for ; Mon, 3 Dec 2012 20:17:59 +0000 (UTC) Received: (qmail 52730 invoked by uid 500); 3 Dec 2012 20:17:58 -0000 Delivered-To: apmail-incubator-flex-dev-archive@incubator.apache.org Received: (qmail 52689 invoked by uid 500); 3 Dec 2012 20:17:58 -0000 Mailing-List: contact flex-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: flex-dev@incubator.apache.org Delivered-To: mailing list flex-dev@incubator.apache.org Received: (qmail 52679 invoked by uid 99); 3 Dec 2012 20:17:58 -0000 Received: from arcas.apache.org (HELO arcas.apache.org) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 03 Dec 2012 20:17:58 +0000 Date: Mon, 3 Dec 2012 20:17:58 +0000 (UTC) From: "Maurice Nicholson (JIRA)" To: flex-dev@incubator.apache.org Message-ID: <1703166765.54904.1354565878569.JavaMail.jiratomcat@arcas> In-Reply-To: <821130926.8912.1353444659728.JavaMail.jiratomcat@arcas> Subject: [jira] [Commented] (FLEX-33273) CSSCondition.matchesStyleClient() is slow and creates excessive garbage MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 [ https://issues.apache.org/jira/browse/FLEX-33273?page=3Dcom.atlassian= .jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=3D1350= 9000#comment-13509000 ]=20 Maurice Nicholson commented on FLEX-33273: ------------------------------------------ Good spot :-) I've updated the attached patch so it works for these test cases too, and i= t still compares very favourably with the original implementation on my har= dware (MacBook Air) and FP (Chrome Release, v11.5): Comparing speed of matching a string in space delimited string. 1000000 loo= ps. TEST OLD MS NEW= MS DELTA OLD MEM NEW MEM DELTA matchesStyleClient({styleName: "barfoo foo"}, "foo") 2432.80 114= .50 -95.29 96.00 0.00 -100.00 matchesStyleClient({styleName: "foobar foo"}, "foo") 2426.50 115= .30 -95.25 96.00 0.00 -100.00 matchesStyleClient({styleName: "foobar foo barfoo"}, "foo") 3673.50 117= .80 -96.79 107.00 0.00 -100.00 matchesStyleClient({styleName: "foo"}, "foo") 1100.80 75= .50 -93.14 97.00 0.00 -100.00 matchesStyleClient({styleName: "foo bar"}, "foo") 2246.30 79= .50 -96.46 95.00 0.00 -100.00 matchesStyleClient({styleName: "bar foo"}, "foo") 2235.50 88= .30 -96.05 97.00 0.00 -100.00 matchesStyleClient({styleName: "baz foo bar"}, "foo") 3318.30 94= .30 -97.16 107.00 0.00 -100.00 matchesStyleClient({styleName: "foobar"}, "foo") 1265.50 97= .50 -92.30 92.00 0.00 -100.00 matchesStyleClient({styleName: "foofoo bar"}, "foo") 2504.80 125= .30 -95.00 94.00 0.00 -100.00 matchesStyleClient({styleName: "fo"}, "foo") 1013.80 67= .30 -93.36 92.00 0.00 -100.00 matchesStyleClient({styleName: "fooo"}, "foo") 1143.50 95= .80 -91.62 92.00 0.00 -100.00 matchesStyleClient({styleName: "2foo bar"}, "foo") 2291.00 102= .00 -95.55 92.00 0.00 -100.00 matchesStyleClient({styleName: "foo2 bar"}, "foo") 2294.30 100= .50 -95.62 92.00 0.00 -100.00 matchesStyleClient({styleName: ""}, "foo") 598.30 55= .30 -90.76 128.00 0.00 -100.00 matchesStyleClient({styleName: null}, "foo") 58.00 57= .80 -0.34 0.00 0.00 0.00 matchesStyleClient({styleName: [object Object]}, "foo") 84.50 56= .80 -32.78 0.00 0.00 0.00 The new version looks like this: public function matchesStyleClient(object:IAdvancedStyleClient):Boolean { if (kind =3D=3D CSSConditionKind.CLASS) { const styleName:String =3D object.styleName as String; if (!styleName) return false; // Look for a match in a potential list of styleNames var index:int =3D styleName.indexOf(value); while (index !=3D -1) { var next:int =3D index + value.length; if ((index =3D=3D 0 || styleName.charAt(index - 1) =3D=3D '= ') && (next =3D=3D styleName.length || styleName.charAt(next)= =3D=3D ' ')) return true; index =3D styleName.indexOf(value, next) } return false; } else if (kind =3D=3D CSSConditionKind.ID) { return (object.id =3D=3D value); } else if (kind =3D=3D CSSConditionKind.PSEUDO) { return (object.matchesCSSState(value)); } return false; } =20 > CSSCondition.matchesStyleClient() is slow and creates excessive garbage > ----------------------------------------------------------------------- > > Key: FLEX-33273 > URL: https://issues.apache.org/jira/browse/FLEX-33273 > Project: Apache Flex > Issue Type: Improvement > Components: Styles > Affects Versions: Adobe Flex SDK 4.1 (Release), Adobe Flex SDK 4.5 (Re= lease), Adobe Flex SDK 4.5.1 (Release), Adobe Flex SDK 4.6 (Release) > Reporter: Maurice Nicholson > Assignee: Fr=C3=A9d=C3=A9ric THOMAS > Labels: patch, performance > Attachments: FLEX-33273.patch, PerformanceTest.zip > > > CSSCondition.matchesStyleClient() is called *very* frequently during layo= ut of components in many different scenarios. > I've done a lot of profiling of Flex apps and it comes up again and again= . > The current implementation is slow and creates unnecessary garbage (which= slows down the runtime further, since it needs to collect the garbage inst= ead of doing more useful things). > Here is the current implementation: > {code} > public function matchesStyleClient(object:IAdvancedStyleClient):Boole= an > { > var match:Boolean =3D false; > if (kind =3D=3D CSSConditionKind.CLASS) > { > if (object.styleName !=3D null && object.styleName is String) > { > // Look for a match in a potential list of styleNames=20 > var styleNames:Array =3D object.styleName.split(/\s+/); > for (var i:uint =3D 0; i < styleNames.length; i++) > { > if (styleNames[i] =3D=3D value) > { > match =3D true; > break; > } > } > } > } > else if (kind =3D=3D CSSConditionKind.ID) > { > if (object.id =3D=3D value) > match =3D true; > } > else if (kind =3D=3D CSSConditionKind.PSEUDO) > { > if (object.matchesCSSState(value)) > match =3D true; > } > return match; > } > {code} > Here is what I suggest instead: > {code} > public function matchesStyleClient(object:IAdvancedStyleClient):Boole= an > { > var match:Boolean =3D false; > if (kind =3D=3D CSSConditionKind.CLASS) > { > const styleName:String =3D object.styleName as String; > if (styleName) > { > // Look for a match in a potential list of styleNames=20 > FIND: > { > var index:int =3D styleName.indexOf(value); > if (index =3D=3D -1) > { > break FIND; > } > if (index !=3D 0 && styleName.charAt(index - 1) !=3D = ' ') > { > break FIND; > } > const next:int =3D index + value.length; > if (next !=3D styleName.length && styleName.charAt(ne= xt) !=3D ' ') > { > break FIND; > } > match =3D true; > } > } > } > else if (kind =3D=3D CSSConditionKind.ID) > { > if (object.id =3D=3D value) > match =3D true; > } > else if (kind =3D=3D CSSConditionKind.PSEUDO) > { > if (object.matchesCSSState(value)) > match =3D true; > } > return match; > } > {code} > There are obviously more concise ways to express this code, but the above= seems to match the current style more or less. > Here is the output from a benchmark I created using Grant Skinner's Perfo= rmanceTest v2 Beta, comparing the current version and the suggested version= : > {noformat} > Comparing speed of matching a string in space delimited string. 1000000 l= oops. > Test Old ms N= ew ms Speedup Old mem New mem Change > matchesStyleClient(styleName: "foo", value: "foo") 1006.00 1= 81.00 -82.0 123.00 0.00 -100.0 > matchesStyleClient(styleName: "foo bar", value: "foo") 2107.00 2= 06.80 -90.2 115.00 0.00 -100.0 > matchesStyleClient(styleName: "bar foo", value: "foo") 2099.80 2= 32.30 -88.9 117.00 0.00 -100.0 > matchesStyleClient(styleName: "baz foo bar", value: "foo") 3193.80 2= 51.30 -92.1 119.00 0.00 -100.0 > matchesStyleClient(styleName: "foobar", value: "foo") 1169.50 1= 92.00 -83.6 112.00 0.00 -100.0 > matchesStyleClient(styleName: "foofoo bar", value: "foo") 2273.80 1= 91.30 -91.6 116.00 0.00 -100.0 > matchesStyleClient(styleName: "fo", value: "foo") 918.80 1= 41.00 -84.7 108.00 0.00 -100.0 > matchesStyleClient(styleName: "fooo", value: "foo") 1052.80 1= 92.00 -81.8 108.00 0.00 -100.0 > matchesStyleClient(styleName: "2foo bar", value: "foo") 2149.50 2= 05.30 -90.4 116.00 0.00 -100.0 > matchesStyleClient(styleName: "foo2 bar", value: "foo") 3849.50 1= 90.80 -95.0 111.00 0.00 -100.0 > matchesStyleClient(styleName: "", value: "foo") 1801.80 1= 41.00 -92.2 132.00 0.00 -100.0 > {noformat} > As you can see, the new version doesn't create garbage, and is at least 8= 0% faster in the above test cases. > I would be happy to contribute a patch and a FlexUnit test, but I haven't= seen any existing FlexUnit tests in the current source tree, so not sure w= here to put it. > Otherwise Mustella seems like a beast to get to know and run, so I will n= eed some guidance as to what to do if you require new Mustella tests. -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrato= rs For more information on JIRA, see: http://www.atlassian.com/software/jira