You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(5) |
Nov
(68) |
Dec
(77) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(75) |
Feb
(84) |
Mar
(89) |
Apr
(96) |
May
(52) |
Jun
(73) |
Jul
(99) |
Aug
(46) |
Sep
(40) |
Oct
(46) |
Nov
(45) |
Dec
(25) |
2004 |
Jan
(13) |
Feb
(74) |
Mar
(40) |
Apr
(18) |
May
(31) |
Jun
(1) |
Jul
(16) |
Aug
(1) |
Sep
(21) |
Oct
(19) |
Nov
(10) |
Dec
(16) |
2005 |
Jan
(4) |
Feb
(12) |
Mar
(46) |
Apr
(33) |
May
(64) |
Jun
(1) |
Jul
(60) |
Aug
(31) |
Sep
(26) |
Oct
(24) |
Nov
(37) |
Dec
(10) |
2006 |
Jan
(3) |
Feb
(31) |
Mar
(122) |
Apr
(22) |
May
(4) |
Jun
|
Jul
|
Aug
(2) |
Sep
(4) |
Oct
(8) |
Nov
(3) |
Dec
|
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
(3) |
Oct
|
Nov
|
Dec
|
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(2) |
Dec
(8) |
From: Keats K. <ke...@xa...> - 2006-03-27 17:44:24
|
>I'll also look at making $Text.formatDate cache the SimpleTextFormat objects >that it creates and run some profiling to see whether or not this is really >an advantage... > > Yes the formatDate() method was kind of a quick hack. At one point I had written a DateTool, but I never got it clean enough to commit to CVS (and now I've lost it). Perhaps I'll give it another whack. It's actually fairly complicated, given all the different date formats and localization etc. It would be nice if the tool could pick up the locale from the request, but then it would be Servlet specific. But something simple would probably be useful for parsing and formatting dates. I'm thinking a factory that would produce date wrappers. E.g., #set $dt = $DateFactory.parse("27-Mar-2006", "dd-MMM-yyyy") #set $dt.Format.Short = "MM/dd/yyyy" #set $dt.Format.Default = "dd-MMM-yyyy" Default format: $dt ==> 27-Mar-2006 Short format: $dt.Format.Short ==> 02/27/2006 #set $dt = $dt.addMonths(1) New date: $dt ==> 27-Apr-2006 etc. Thoughts? Keats >A > > > >>Of course then this offers little benefit, if not making things >>worse, over using Keats' #bean approach... >> >>#formatDate($createdAt) >> >>vs. >> >>$sharedFormatter.format($createdAt) >> >>...and with my own caveats about using "directive" style macros I >>think the latter, Keats' scenario is better. >> >>Ahhhh now I'm thinking in Spring terms, and changing the topic... hmm >>it would be really nice if we could add some kind of context provider >>that populates the context with all the beans from a Spring >>BeanContext :) >> >>Cheers >> >> >> >>------------------------------------------------------- >>This SF.Net email is sponsored by xPML, a groundbreaking scripting language >>that extends applications into web and mobile media. Attend the live >>webcast and join the prime developer group breaking into this new coding >>territory! >>http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642 >>_______________________________________________ >>Webmacro-user mailing list >>Web...@li... >>https://lists.sourceforge.net/lists/listinfo/webmacro-user >> >> > > >------------------------------------------------------- >This SF.Net email is sponsored by xPML, a groundbreaking scripting language >that extends applications into web and mobile media. Attend the live webcast >and join the prime developer group breaking into this new coding territory! >http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642 >_______________________________________________ >Webmacro-user mailing list >Web...@li... >https://lists.sourceforge.net/lists/listinfo/webmacro-user > > > |
From: Alex Twisleton-Wykeham-F. <al...@fi...> - 2006-03-27 10:39:50
|
On Mon 27 March 2006 11:28, Marc Palmer wrote: > On 27 Mar 2006, at 11:13, Alex Twisleton-Wykeham-Fiennes wrote: > > On Mon 27 March 2006 11:00, Marc Palmer wrote: > >> On 27 Mar 2006, at 02:47, Sven Schliesing wrote: > >>> That's exactly what I looked for. > >> > >> There's another, potentially cleaner way... > >> > >> ----------------- "mymacros.wmm": > >> > >> #macro formatDate($d) > >> $Text.formatDate($d, "dd.MM.yyyy, HH:mm") > >> #end > >> > >> ----------------- "yourtemplate.wmt": > >> > >> #include as macro "mymacros.wmm" > >> > >> #formatDate($createdAt) > > > > Just to jump in for a moment - this will create a new > > SimpleDateFormat object > > every single time that it is invoked. If you know that you are > > going to be > > formatting a lot of different dates with the same format then it is > > considerably more efficient to drop in a dedicated wrapper around > > an instance > > of SimpleDateFormat that gives you the format that you want as > > otherwise each > > time that you invoke it, it will have to parse your "dd.MM.yyyy, > > HH:mm" > > format string, build the internal representation and then format > > the Date > > which is relatively expensive. > > You're absolutely right, but that can be dealt with using a macro > plus a #bean to create a "static" shared instance of the formatter? I'll also look at making $Text.formatDate cache the SimpleTextFormat objects that it creates and run some profiling to see whether or not this is really an advantage... A > Of course then this offers little benefit, if not making things > worse, over using Keats' #bean approach... > > #formatDate($createdAt) > > vs. > > $sharedFormatter.format($createdAt) > > ...and with my own caveats about using "directive" style macros I > think the latter, Keats' scenario is better. > > Ahhhh now I'm thinking in Spring terms, and changing the topic... hmm > it would be really nice if we could add some kind of context provider > that populates the context with all the beans from a Spring > BeanContext :) > > Cheers > > > > ------------------------------------------------------- > This SF.Net email is sponsored by xPML, a groundbreaking scripting language > that extends applications into web and mobile media. Attend the live > webcast and join the prime developer group breaking into this new coding > territory! > http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642 > _______________________________________________ > Webmacro-user mailing list > Web...@li... > https://lists.sourceforge.net/lists/listinfo/webmacro-user |
From: Marc P. <ma...@an...> - 2006-03-27 10:31:05
|
On 27 Mar 2006, at 11:13, Alex Twisleton-Wykeham-Fiennes wrote: > On Mon 27 March 2006 11:00, Marc Palmer wrote: >> On 27 Mar 2006, at 02:47, Sven Schliesing wrote: >>> That's exactly what I looked for. >> >> There's another, potentially cleaner way... >> >> ----------------- "mymacros.wmm": >> >> #macro formatDate($d) >> $Text.formatDate($d, "dd.MM.yyyy, HH:mm") >> #end >> >> ----------------- "yourtemplate.wmt": >> >> #include as macro "mymacros.wmm" >> >> #formatDate($createdAt) > > Just to jump in for a moment - this will create a new > SimpleDateFormat object > every single time that it is invoked. If you know that you are > going to be > formatting a lot of different dates with the same format then it is > considerably more efficient to drop in a dedicated wrapper around > an instance > of SimpleDateFormat that gives you the format that you want as > otherwise each > time that you invoke it, it will have to parse your "dd.MM.yyyy, > HH:mm" > format string, build the internal representation and then format > the Date > which is relatively expensive. You're absolutely right, but that can be dealt with using a macro plus a #bean to create a "static" shared instance of the formatter? Of course then this offers little benefit, if not making things worse, over using Keats' #bean approach... #formatDate($createdAt) vs. $sharedFormatter.format($createdAt) ...and with my own caveats about using "directive" style macros I think the latter, Keats' scenario is better. Ahhhh now I'm thinking in Spring terms, and changing the topic... hmm it would be really nice if we could add some kind of context provider that populates the context with all the beans from a Spring BeanContext :) Cheers |
From: Nikhil G. D. <ng...@ce...> - 2006-03-27 10:26:34
|
I have written a static function and then use the "Functions" feature. The static function uses a per-request SimpleDateFormat so it is quite efficient. So in webmacro I can write: <input type="text" value="$formatInputDate($d)"> OR <td>$formatDate($d)</td> etc. Alex Twisleton-Wykeham-Fiennes wrote: > On Mon 27 March 2006 11:00, Marc Palmer wrote: > >> On 27 Mar 2006, at 02:47, Sven Schliesing wrote: >> >>> That's exactly what I looked for. >>> >> There's another, potentially cleaner way... >> >> ----------------- "mymacros.wmm": >> >> #macro formatDate($d) >> $Text.formatDate($d, "dd.MM.yyyy, HH:mm") >> #end >> >> ----------------- "yourtemplate.wmt": >> >> #include as macro "mymacros.wmm" >> >> #formatDate($createdAt) >> > > Just to jump in for a moment - this will create a new SimpleDateFormat object > every single time that it is invoked. If you know that you are going to be > formatting a lot of different dates with the same format then it is > considerably more efficient to drop in a dedicated wrapper around an instance > of SimpleDateFormat that gives you the format that you want as otherwise each > time that you invoke it, it will have to parse your "dd.MM.yyyy, HH:mm" > format string, build the internal representation and then format the Date > which is relatively expensive. > > <snip> > > Alex > > > ------------------------------------------------------- > This SF.Net email is sponsored by xPML, a groundbreaking scripting language > that extends applications into web and mobile media. Attend the live webcast > and join the prime developer group breaking into this new coding territory! > http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642 > _______________________________________________ > Webmacro-user mailing list > Web...@li... > https://lists.sourceforge.net/lists/listinfo/webmacro-user > |
From: Alex Twisleton-Wykeham-F. <al...@fi...> - 2006-03-27 10:13:30
|
On Mon 27 March 2006 11:00, Marc Palmer wrote: > On 27 Mar 2006, at 02:47, Sven Schliesing wrote: > > That's exactly what I looked for. > > There's another, potentially cleaner way... > > ----------------- "mymacros.wmm": > > #macro formatDate($d) > $Text.formatDate($d, "dd.MM.yyyy, HH:mm") > #end > > ----------------- "yourtemplate.wmt": > > #include as macro "mymacros.wmm" > > #formatDate($createdAt) Just to jump in for a moment - this will create a new SimpleDateFormat object every single time that it is invoked. If you know that you are going to be formatting a lot of different dates with the same format then it is considerably more efficient to drop in a dedicated wrapper around an instance of SimpleDateFormat that gives you the format that you want as otherwise each time that you invoke it, it will have to parse your "dd.MM.yyyy, HH:mm" format string, build the internal representation and then format the Date which is relatively expensive. <snip> Alex |
From: Marc P. <ma...@an...> - 2006-03-27 10:01:41
|
On 27 Mar 2006, at 02:47, Sven Schliesing wrote: > That's exactly what I looked for. > There's another, potentially cleaner way... ----------------- "mymacros.wmm": #macro formatDate($d) $Text.formatDate($d, "dd.MM.yyyy, HH:mm") #end ----------------- "yourtemplate.wmt": #include as macro "mymacros.wmm" #formatDate($createdAt) That's the way I would do it, as the usage is cleaner. However using directives/macros has the disadvantage of whitespace confusion/ issues. i.e. <img alt="#formatDate($createdAt)"/> is problematic, you have to do <img alt=" #formatDate($createdAt)"/> ... intuitive eh :( ! Personally, I wish that #macro or a similar macro function did not define what looks like a "directive". "#directive" would have been the right name for #macrom with hindsight (although caveats about not really being a directive!)... and in a strict sense I think it would have been nicer (with hindsight) to make it so that you have to use a directive to eval them. Injecting directive look-alikes into the templates like this is potentially confusing. cheers |
From: Sven S. <sv...@sc...> - 2006-03-27 01:47:14
|
That's exactly what I looked for. Big Thanks! Sven Keats Kirsch wrote: > If you define the method as a function you can make it a bit shorter. > One way is to add this to your WebMacro.properties file: > > Functions.formatDate=org.webmacro.servlet.TextTool.formatDate > > Then you can drop the Text part, and use: > > $formatDate($createdAt, "dd.MM.yyyy, HH:mm") > > Other options would be to drop a date formatter into your context and > use that, or develop your own DateTool or something like that. You > could even create a custom date object with predefined formats. E.g., > > #bean $wmDate=WMDate initArgs=$createdAt > $wmDate.DATETIME1 > > Hope this helps. > > Keats |
From: Keats K. <ke...@xa...> - 2006-03-26 23:09:21
|
Sven Schliesing wrote: > is there a shorter way for this? > $Text.formatDate($createdAt, "dd.MM.yyyy, HH:mm") If you define the method as a function you can make it a bit shorter. One way is to add this to your WebMacro.properties file: Functions.formatDate=org.webmacro.servlet.TextTool.formatDate Then you can drop the Text part, and use: $formatDate($createdAt, "dd.MM.yyyy, HH:mm") Other options would be to drop a date formatter into your context and use that, or develop your own DateTool or something like that. You could even create a custom date object with predefined formats. E.g., #bean $wmDate=WMDate initArgs=$createdAt $wmDate.DATETIME1 Hope this helps. Keats > > Thanks in advance > > Sven > |
From: Sven S. <sv...@sc...> - 2006-03-26 21:23:05
|
Hi, is there a shorter way for this? $Text.formatDate($createdAt, "dd.MM.yyyy, HH:mm") Thanks in advance Sven |
From: Alex Twisleton-Wykeham-F. <al...@fi...> - 2006-03-23 14:08:55
|
On Thu 23 March 2006 09:32, Endre St=F8lsvik wrote: > Hi again! > > | ps: Endre: I would be *very* happy to evaluate any actual concrete code > | that you put forward to the list towards performance increases in > | webmacro. > > I must admit that I might have gotten stuck in a wrong argument-line. It > is probably rather the full architecture that I'm annoyed with, where the > synchronization-issues I'm raising is rather a symptom of an underlying > problem (as I percieve it), rather than the problem in itself. well, in which case I rephrase my statement to say that I'd be very happy t= o=20 evaluate your proposed architectural changes to the webmacro tree against t= he=20 current tree with respect to backwards compatability and performance. > A question one could raise in this line of argument is rather _why_ is > there so much hitting at the concurrentmap? Not necessarily _how to > improve the speed_, is my point, although this is obviously also a good > thing to evaluate. I've been looking into this as well, and at present I don't see any trivial= =20 ways of reducing the number of hits on the caches. However, I'm still=20 getting up to speed on the finer points of the (very elegant) architecture= =20 and wouldn't like to suggest any changes without validating that they don't= =20 have some unforseen side effects. > I will try to do some code at some point. But if there isn't a drive in > the community to do this "disentagle" of concerns in WebMacro, we aren't > really aligned. I'm not personally opposed to architectural tweaks, I just find it very=20 difficult to get excited about statements that say "this is bad and should = be=20 changed" rather than "I think that XYZ would be a better way of doing ABC a= nd=20 here are my reasons for suggesting it". > PS: I value the stuff you're doing. It is obviously a good effort, > cleaning up some heavy mess that's left behind after last refactor. I wouldn't say that it is really a heavy mess. Each version of webmacro ha= s=20 been faster and more flexible than the one before, I'm just adding a few mo= re=20 tweaks to the architecture. > PPS: re equals'n'hashCode: how does things end up in the map(s)?=20 There are two models: either invoking CacheManager.get(Object key) and=20 manually adding it if the return is null, or invoking CacheManager.get(Obje= ct=20 key, ResourceLoader helper) which calls back to the helper in the case of t= he=20 the key not being found in the cache. The majority of the time in the profiling, the items are actually in the ca= che=20 already, but they are just being resolved. > Are they=20 > hitting "linear storage" where one in effect ends up with a linked list, > rather than a hashmap? This has been the issue in some of my code, where > hashCode had a very bad distribution, and that _really_ made for slow > accesses. Using JProfiler (my tool of choice at the moment), this was > rather easy to find, as one may "graph-walk" the heap, and this showed > that some elements had a _really_ long way to their GC-roots, running > through a huge line of HashMap.Entry elements' "next" pointers. This is generally caused by having a clumping hashcode() function on your k= ey. =20 The number of buckets in the HashMap should automatically expand once the=20 number of items in the map exceeds the loadFactor x bucketCount on the=20 HashMap. However, if your hashcode function returns either the same value= =20 for multiple keys or the same (value % bucketcount) for multiple keys then= =20 they will tend to bunch together under a single bucket before triggering th= e=20 rebuild. A "good" hashcode implementation will ensure a wide distribution = of=20 keys across the initial buckets and therefore will reduce your chains. However, every single get() call to a Map (for both HashMap, and=20 ConcurrentHashMap) will involve an invocation of hashcode() on the key to=20 find out the bucket to place the key into, followed by a call to equals() o= n=20 all of the items within the bucket chain until it is matched. Therefore an= =20 innefficient algorithm for hashcode and equals can cripple the performance = of=20 the HashMap at multiple levels. Alex |
From: <Web...@St...> - 2006-03-23 09:32:11
|
Hi again! | ps: Endre: I would be *very* happy to evaluate any actual concrete code that | you put forward to the list towards performance increases in webmacro. I must admit that I might have gotten stuck in a wrong argument-line. It is probably rather the full architecture that I'm annoyed with, where the synchronization-issues I'm raising is rather a symptom of an underlying problem (as I percieve it), rather than the problem in itself. A question one could raise in this line of argument is rather _why_ is there so much hitting at the concurrentmap? Not necessarily _how to improve the speed_, is my point, although this is obviously also a good thing to evaluate. I will try to do some code at some point. But if there isn't a drive in the community to do this "disentagle" of concerns in WebMacro, we aren't really aligned. PS: I value the stuff you're doing. It is obviously a good effort, cleaning up some heavy mess that's left behind after last refactor. PPS: re equals'n'hashCode: how does things end up in the map(s)? Are they hitting "linear storage" where one in effect ends up with a linked list, rather than a hashmap? This has been the issue in some of my code, where hashCode had a very bad distribution, and that _really_ made for slow accesses. Using JProfiler (my tool of choice at the moment), this was rather easy to find, as one may "graph-walk" the heap, and this showed that some elements had a _really_ long way to their GC-roots, running through a huge line of HashMap.Entry elements' "next" pointers. Kind regards, Endre. |
From: Alex Twisleton-Wykeham-F. <al...@fi...> - 2006-03-22 16:13:58
|
Keats & Endre On Wed 22 March 2006 14:58, Keats Kirsch wrote: > Your opinion certainly has some merit, but what you're suggesting is a > complete rearchitecture of WM. While that would probably be a good > thing, for now we're just looking at a few little performance tweaks. I would totally agree with that which is why I'm trying to make my changes= =20 transparent from a functionality point of view. I have way too much legacy= =20 code to refactor if the API for webmacro changed. > I think initially WM was envisioned primarily as a templating framework > for Servlet applications, so thread-safety was a big concern. Over time > it has evolved into more of a general purpose templating framework, but > there is still a lot of Servlet-oriented stuff embedded. If we had > developer interest we could start talking about WM3 which might better > decouple various facets. But for now we have a pretty handy little tool > that works pretty well. I totally agree with Keats on this front. Plus, all this talk about the ev= ils=20 of synchronization is a little bit misplaced as well. Synchronization can = be=20 evil for one of two reasons:- =2D threadlocks (which are really deeply evil, but which can be easily avoi= ded=20 by careful design of your synchronized framework) =2D performance overhead of synchronization. Currently the highest amount of CPU usage in my testbed when profiling the= =20 *entire* java runtime (tomcat, JDBC, webmacro, node application server, tes= t=20 application) aside from blocking operations such as socket reads, is=20 ConcurrentHashMap.get being invoked by SimpleCacheManager amongst others. = =20 This is non-synchronized (except when it detects concurrent modification in= =20 which case it re-reads with a synchronized lock, but this is *never*=20 triggering on my test case). Therefore, if you *are* concerned about performance, then don't worry about= =20 the synchronization at all at present. It would be *much* better to work o= ut=20 a way of not hitting the Map quite so heavily which will give you a way=20 better performance response than potentially destabilising your concurrent= =20 access to the library by tweaking the synchronization model for webmacro. The algorithm for ConcurrentHashMap is very clean and very fast and probabl= y=20 isn't going to get much faster. However, the algorithms that are used for= =20 equals() and hashcode() in the objects that are used as keys in the maps, a= nd=20 the initial sizes of the various caches are probably good places to start. Once I've had a look at that then I'm going to try and work out whether the= re=20 are any places in the architecture where Map lookups can be bypassed safely= ,=20 but this is a considerably more complicated issue which involves a lot more= =20 thinking about before any changes are made. Alex ps: Endre: I would be *very* happy to evaluate any actual concrete code th= at=20 you put forward to the list towards performance increases in webmacro. > Keats > > Endre St=F8lsvik wrote: > >| I don't think it's the same at all. Synchronization is a safety measu= re > >| with a small performance penalty. If you can't show that your code is > >| always thread-safe, you should synchronize. > > > >Well, we've managed to reduce this down to what it is: opinions! > > > >I _totally_ don't agree with this: (library) code should _never_ be thre= ad > >safe, as a rule of thumb!! > > > >It is generally the _use_ of (library) code that should ensure thread > >safety, if it is necessary in the situation at hand. > > > >I find the Hashtable and Vector and StringBuffer approach of doing things > >"threadsafe" from the start totally utterly backwards, and happily "java" > >is going directly away from this approach (HashMap, ArrayList and > >StringBuilder). > > > >A library should as a rule of thumb be developed in a way that makes > >synchronization unnecessary and indeed _obvious_, and not include "smart" > >stuff within it that requires synchronization (typical example: internal > >smart-ass caches that are there to reduce the impact of badly written > >code). On this aspect, WebMacro has gotten it totally wrong: WebMacro ha= ve > >_way_ to much bloat in it, due to the fact that it wasn't really decided > >until "recently" that it shouldn't be a "web framework", but rather "a > >macro-merging utility". However, this hasn't been brougth to the end: > >there are still way to much magic, hidden smarties and bloat within > >webmacro. > > > >The very bad examples are the following: > > *) The concept of "the configurable broker", with way too much > >responsibility. > > *) Reloading of templates, thus forking threads!! > > *) Luckily the _downright idiotic_ "time thread" is already gone, so I > >can sleep better at night. > > > >Those things shouldn't have anything to do with the tight little > >macro-merging utility/library that WebMacro ought to be. > > > >I can't see one reason for why WebMacro couldn't be developed in a way > >that would do _all_ synchronization unnecessary (the lazy init of that > >dear name _might_ constitute an exception, but even there, since this is > >utterly exceptional, this could be done "every time" instead). > > Templates should be immutable and not contain state at all, so that th= ey > >could be shared amongst threads (as they obviously are), but the actual > >sharing of instances should be done in an application-specific way: if y= ou > >didn't handle the caching (and thus synchronization) yourself (by some > >plugin, or whatever), you wouldn't get any, and the whole thing was > >totally linear and un-synchronized (make Template, make Context (or just= a > >Map?), merge()). > > > > > >Note that this isn't just a point about the syncronization per se, but as > >an architectural idea: if things are straightforward, linear, and without > >hidden magic, they _tend to not need_ synchronization, and tend to be mu= ch > >easier to understand and not least debug when things doesn't go your way. > >Not to mention the "safe feeling" one gets when a library is truly > >understood and the call-paths are obvious and linear. > > > >Kind regards, > >Endre. > > ------------------------------------------------------- > This SF.Net email is sponsored by xPML, a groundbreaking scripting langua= ge > that extends applications into web and mobile media. Attend the live > webcast and join the prime developer group breaking into this new coding > territory! > http://sel.as-us.falkag.net/sel?cmd=3Dlnk&kid=3D110944&bid=3D241720&dat= =3D121642 > _______________________________________________ > Webmacro-user mailing list > Web...@li... > https://lists.sourceforge.net/lists/listinfo/webmacro-user |
From: Keats K. <ke...@xa...> - 2006-03-22 14:58:15
|
Your opinion certainly has some merit, but what you're suggesting is a complete rearchitecture of WM. While that would probably be a good thing, for now we're just looking at a few little performance tweaks. I think initially WM was envisioned primarily as a templating framework for Servlet applications, so thread-safety was a big concern. Over time it has evolved into more of a general purpose templating framework, but there is still a lot of Servlet-oriented stuff embedded. If we had developer interest we could start talking about WM3 which might better decouple various facets. But for now we have a pretty handy little tool that works pretty well. Keats Endre Stølsvik wrote: >| I don't think it's the same at all. Synchronization is a safety measure with >| a small performance penalty. If you can't show that your code is always >| thread-safe, you should synchronize. > >Well, we've managed to reduce this down to what it is: opinions! > >I _totally_ don't agree with this: (library) code should _never_ be thread >safe, as a rule of thumb!! > >It is generally the _use_ of (library) code that should ensure thread >safety, if it is necessary in the situation at hand. > >I find the Hashtable and Vector and StringBuffer approach of doing things >"threadsafe" from the start totally utterly backwards, and happily "java" >is going directly away from this approach (HashMap, ArrayList and >StringBuilder). > >A library should as a rule of thumb be developed in a way that makes >synchronization unnecessary and indeed _obvious_, and not include "smart" >stuff within it that requires synchronization (typical example: internal >smart-ass caches that are there to reduce the impact of badly written >code). On this aspect, WebMacro has gotten it totally wrong: WebMacro have >_way_ to much bloat in it, due to the fact that it wasn't really decided >until "recently" that it shouldn't be a "web framework", but rather "a >macro-merging utility". However, this hasn't been brougth to the end: >there are still way to much magic, hidden smarties and bloat within >webmacro. > >The very bad examples are the following: > *) The concept of "the configurable broker", with way too much >responsibility. > *) Reloading of templates, thus forking threads!! > *) Luckily the _downright idiotic_ "time thread" is already gone, so I >can sleep better at night. > >Those things shouldn't have anything to do with the tight little >macro-merging utility/library that WebMacro ought to be. > >I can't see one reason for why WebMacro couldn't be developed in a way >that would do _all_ synchronization unnecessary (the lazy init of that >dear name _might_ constitute an exception, but even there, since this is >utterly exceptional, this could be done "every time" instead). > Templates should be immutable and not contain state at all, so that they >could be shared amongst threads (as they obviously are), but the actual >sharing of instances should be done in an application-specific way: if you >didn't handle the caching (and thus synchronization) yourself (by some >plugin, or whatever), you wouldn't get any, and the whole thing was >totally linear and un-synchronized (make Template, make Context (or just a >Map?), merge()). > > >Note that this isn't just a point about the syncronization per se, but as >an architectural idea: if things are straightforward, linear, and without >hidden magic, they _tend to not need_ synchronization, and tend to be much >easier to understand and not least debug when things doesn't go your way. >Not to mention the "safe feeling" one gets when a library is truly >understood and the call-paths are obvious and linear. > >Kind regards, >Endre. > > > |
From: <Web...@St...> - 2006-03-22 14:34:44
|
| I don't think it's the same at all. Synchronization is a safety measure with | a small performance penalty. If you can't show that your code is always | thread-safe, you should synchronize. Well, we've managed to reduce this down to what it is: opinions! I _totally_ don't agree with this: (library) code should _never_ be thread safe, as a rule of thumb!! It is generally the _use_ of (library) code that should ensure thread safety, if it is necessary in the situation at hand. I find the Hashtable and Vector and StringBuffer approach of doing things "threadsafe" from the start totally utterly backwards, and happily "java" is going directly away from this approach (HashMap, ArrayList and StringBuilder). A library should as a rule of thumb be developed in a way that makes synchronization unnecessary and indeed _obvious_, and not include "smart" stuff within it that requires synchronization (typical example: internal smart-ass caches that are there to reduce the impact of badly written code). On this aspect, WebMacro has gotten it totally wrong: WebMacro have _way_ to much bloat in it, due to the fact that it wasn't really decided until "recently" that it shouldn't be a "web framework", but rather "a macro-merging utility". However, this hasn't been brougth to the end: there are still way to much magic, hidden smarties and bloat within webmacro. The very bad examples are the following: *) The concept of "the configurable broker", with way too much responsibility. *) Reloading of templates, thus forking threads!! *) Luckily the _downright idiotic_ "time thread" is already gone, so I can sleep better at night. Those things shouldn't have anything to do with the tight little macro-merging utility/library that WebMacro ought to be. I can't see one reason for why WebMacro couldn't be developed in a way that would do _all_ synchronization unnecessary (the lazy init of that dear name _might_ constitute an exception, but even there, since this is utterly exceptional, this could be done "every time" instead). Templates should be immutable and not contain state at all, so that they could be shared amongst threads (as they obviously are), but the actual sharing of instances should be done in an application-specific way: if you didn't handle the caching (and thus synchronization) yourself (by some plugin, or whatever), you wouldn't get any, and the whole thing was totally linear and un-synchronized (make Template, make Context (or just a Map?), merge()). Note that this isn't just a point about the syncronization per se, but as an architectural idea: if things are straightforward, linear, and without hidden magic, they _tend to not need_ synchronization, and tend to be much easier to understand and not least debug when things doesn't go your way. Not to mention the "safe feeling" one gets when a library is truly understood and the call-paths are obvious and linear. Kind regards, Endre. |
From: Keats K. <ke...@xa...> - 2006-03-20 17:41:23
|
Endre Stølsvik wrote: >On Fri, 17 Mar 2006, Keats Kirsch wrote: > >I do get that _Templates_ are shared. But are all Macro-implementing >objects in WebMacro shared? > > A compiled (built) template has a list of Macro objects that get evaluated (expanded) on each request. These include any variables (unless they've been optimized into text at build time), as well as directives, and functions. Most of the time the state for these macros is stored in the context, so things are thread-safe. Any exception would require synchronization. >I am just asking here, really. > >(.. maybe this then should be worked over?! The synched Map/Set/Whatever >lookup must be hitting hard?!). > > There is very little synchronization required, because the state is generally stored in the Context. This has been further reduced by using the concurrent utilities. If you see anything being synchronized that has a real performance impact, we should look at it. >| An alternative, if you *really* can't stand synchronization, would be to get >| rid of the member variable altogether and just have the display name computed >| every time it is requested. > >That is a very good idea, and way better if this is a method that wont be >called in the standard case. > >| I don't see any performance benefit to this, but >| it would keep the state from being modified. > >Immutables are the very best paradigm when it comes to multithreading, if >possible. IMO. > As a general rule, I agree. But there are always exceptions. In this case we're talking about exceptional cases. I think it's really 6 of one, a half dozen of the other. In either case we just need to comment the code so that future developers will understand what's going on. >| I also agree that it is a mistake to optimize exceptional cases without any >| empirical evidence of a performance issue. This is a classic case of what >| Bruce Eckel ("Thinking in Java") calls "premature optimization". > >Well, the same goes for syncronization, doesn't it? > >Don't synch if you don't need to, kinda. And if you need to, then do you >really?? (.. and here you don't, as you perfectly point out). > > I don't think it's the same at all. Synchronization is a safety measure with a small performance penalty. If you can't show that your code is always thread-safe, you should synchronize. Fortunately there are various ways to reduce the impact of this; such as using Doug Lea's concurrent utilities. Keats >Regards, >Endre. > > |
From: <Web...@St...> - 2006-03-20 15:54:51
|
| > | > If an object that implements Macro is _shared across threads_, then _this_ | > class should do synchs on methods that change its internal state (and | > generally not using the "method syncrhonziation" paradigm - read up on | > "monitors"). But why should the general Macro-implementing objects of | > WebMacro be shared across threads?! | | Let's just assume that I don't know what I'm talking about for a moment. I do think that you know your stuff, and the optimzations you're doing to WebMacro now are _just great_. I guess there is some underlying disagreement to some small aspects of multithreading here, read at end. | Please explain at what point in the following I am on crack:- | | - Macro is an interface. | - interfaces cannot specify synchronized in their declarations according to | the java language definition. | - Variable implements Macro. | - Variable has a method that checks for an internal variable to see if it is | null and sets it if it is null. | - I would like this initialisation to only occur once so I want to synchronize | on something to achieve this. | - I can't synchronize on the variable because it is null (initially) | - I'm therefore left with the choice of synchronizing on the Object itself or | creating a second Object inside the Variable to synchronize on. | | Am I missing something? Well, no, not unless the option suggested by Keats should be counted as a miss. But if this thing only synchs on the one explicit feature (the name-thingy), then it definately should have its own synch - or else you'll create "false contention". But avoiding synchs altoghether is definately the best - using immutables, and/or "instances are created per context" or similar logic. I can't understand that much anything in WebMacro should be shared, less the Templates itself due to "precalculations" using the introspection engine stuff. But the templates should again not contain any _state_, so that they can be shared as an immutable. | | > | ps synchronizing is really not the overhead that it used to be in older | > | JVMs and it *really* makes your life easier to not have any | > | multi-threading bugs... | > | > Contended synchs are hell in any case. | > | > A synch, contended or not, have to flush all dirty cache to memory whether | > or not it is necessary. This is bad, and one should _not_ use synchs | > unless it is multithreaded accessed. | | But it *is* multithreaded accessed. Okay - then "the Keats option" is .. an option. But why is it multitreaded accessed? | And even if it wasn't, you are not sure | that it isn't or that it won't be in the future, so you write your code safe | and then optimise it when / if performance becomes an issue. I guess it is here we disagree. I think that the javadoc should state "this ain't multithread-safe, don't share it, or else do synchs yourself", like the Collections framework, or maybe "instances of this class are immutable, so share it as much as you want" You're probably in the StringBuffer, Vector, Hastable camp, while I'm firmly in the other camp when it comes to synching: StringBuilder, ArrayList, Hashmap. Regards, Endre. |
From: <Web...@St...> - 2006-03-20 13:59:26
|
On Fri, 17 Mar 2006, Keats Kirsch wrote: | I haven't followed the precise details of the debate, but it seems to me that | Alex is correct. That is, optimize for the non-exception case by not | constructing the display name for the variable, but synchronize access to the | method that does the lazy instantiation of the display name. Without | synchronization it is possible that two threads (two requests for the same | template) could try to create the display name at the same time with | unpredictable results. In most cases, with most microprocessors, it wouldn't | matter, as the processors provide stronger memory barriers than are required | by the Java specs. But why take the chance, especially when the cost is | minuscule? I do get that _Templates_ are shared. But are all Macro-implementing objects in WebMacro shared? I am just asking here, really. (.. maybe this then should be worked over?! The synched Map/Set/Whatever lookup must be hitting hard?!). | | An alternative, if you *really* can't stand synchronization, would be to get | rid of the member variable altogether and just have the display name computed | every time it is requested. That is a very good idea, and way better if this is a method that wont be called in the standard case. | I don't see any performance benefit to this, but | it would keep the state from being modified. Immutables are the very best paradigm when it comes to multithreading, if possible. IMO. | | I also agree that it is a mistake to optimize exceptional cases without any | empirical evidence of a performance issue. This is a classic case of what | Bruce Eckel ("Thinking in Java") calls "premature optimization". Well, the same goes for syncronization, doesn't it? Don't synch if you don't need to, kinda. And if you need to, then do you really?? (.. and here you don't, as you perfectly point out). Regards, Endre. |
From: <Web...@St...> - 2006-03-20 13:47:45
|
On Fri, 17 Mar 2006, Alex Twisleton-Wykeham-Fiennes wrote: | On Fri 17 March 2006 11:23, Endre St=F8lsvik wrote: | > On Mon, 13 Mar 2006, Alex Twisleton-Wykeham-Fiennes wrote: | > | > I do it using _a new_ FastWriter with a temporary backing, then i= f | > | > everything went right, I put the result to the FastWriter. | > | | > | Do you use a seperate Context for each portlet as well? | > | > Yes. | > But assuming that the Portlets aren't _pure_ evil, this would have be= en a | > big thing: I could just have recreated the initial state before each | > rendering, by using a "weird-long-named" context-var for "my state", | > hoping that the corelet wouldn't intentially mess things up. | > | > But I do make a new Context, due to this concern. | > | > | > This temporary backing paradigm obviously isn't the best, and a | > | > mark/reset/flush paradigm would be much better for my part. | > | | > | I can see where you are coming from on this, but it is very hard to= state | > | what the side effects of flushing the FastWriter early and / or rol= ling | > | it back to an earlier state. | > | > Why is that? This seems completely illogical to me, I can't see at al= l | > where you're coming from. | > | > If I still make new Contexts, and you understand that each portlet is= "on | > its own" (with a logical separate context too), and if I don't commit | > bytes to the browser-stream before flush, then "rolling back" is _exa= ctly_ | > the same as ditching the buffer, _as I do now_. |=20 | I understand exactly what you have at the moment, and I understand what= is=20 | being suggested, but let me just recap for a moment:- |=20 | - you have a series of portlets. Currently you are rendering these by=20 | creating a new Context and a new FastWriter, doing all the work and the= n=20 | dropping the contents of the FastWriter (which will either contain your= =20 | portlet or your error report) into the master FastWriter. No, it doesn't contain the error-report. If it fails, I drop the=20 fastwriter, and then actually make another one, which I run the=20 error-template in, and use that (but I could have just dropped it, and=20 rendered the error-template "directly"). |=20 | - you are proposing to save the creation time of a new FastWriter by us= ing the=20 | master FastWriter for the global template page and resetting it as nece= ssary=20 | to handle the consequences (I think the use of flush in your mark/reset= /flush=20 | is maybe what is confusing because flushing by definition drops the con= tents=20 | of the FastWriter out to the output stream which is probably not what y= ou=20 | mean). Flush if it went Okay (as stated repeatedly, I believe?). That way, the=20 user would get the portlets rendered in their browser as they were=20 finished, giving an impression of something happening, even if some stupi= d=20 portlet later in the line use too much time. Rollback ("reset") if it didn't, and then render the error-template, and=20 then flush. |=20 | Now, just for a moment in order to play devils advocate: supposing tha= t we do=20 | have this #flush command that Keats mentioned, and suppose one of your=20 | portlet implementors executes #flush inside one of your portlet and the= bytes=20 | (both before and after your mark) are flushed out to the output stream.= You=20 | then try and do a reset, but the reset point along with all the data be= fore=20 | and after it has already been sent down-stream. Why whould i let the user do #flush? FastWriter.flush() would be good enough for me - I'M THE PORTAL! The _working_ trio mark(), reset() and flush() is what I'm requesting. In _production_ environments, where one is very sure about the quality of= =20 portlets, one could potentially let the #flush actually map to the=20 .flush(), instead of just noop'ing. |=20 | Personally, I think that you already have a nicely encapsulated safe st= ructure=20 | for your portlets with a dedicated Context and a dedicated FastWriter f= or=20 | each portlet. Me too thinks so! But there is way to much byte-arrays around, and if=20 things goes OK (no errors to wrap), then there is _lots_ of byte-copying=20 that is totally utterly useless. Do you see this point? I'm not quite sure how the byte-arrays work now, after your fixups (whose= =20 bugs seem _amazing_ that have been around so long!) - are they still=20 recycled? See, object creation is rather cheap these days, but it is still faster t= o=20 _not_ create objects. And byte-array copies do take _some_ time, most probably unnecessary. | Error failure is encapsulated and you don't drop the result of your=20 | parsing / error catching out to your master FastWriter until it is=20 | completed. If you are concerned about the overhead of generating lots=20 | (1 per portlet) of new FastWriter instances, then I would use just one=20 | FastWriter that is shared between all of your Portlets, and your=20 | sequence would be:- |=20 | - create Portlet FastWriter | - foreach portlet in portlets | - create new Portlet Context | - reset Portlet FastWriter | try { | - render portlet with Portlet Context to Portlet FastWriter | } catch (exception) { | - reset FastWriter | - render error with Portlet Context to Portlet FastWriter | } | - write Portlet FastWriter to Servlet FastWriter | } | - write Servlet FastWriter to OutputStream Actually that's what I _believed_ that it did already, due to the=20 pooling/recycling. I still use WM 1.1, so I guess that still holds true? But btw, isn't the FastWriter thing holding some interal state? |=20 | Now, you still have all of your encapsulation, your rollbacks work, you= are=20 | creating at most one FastWriter beyond where you are, and it really doe= sn't=20 | matter what happens inside the rendering loop and you don't need to mak= e any=20 | functional changes to how the FastWriter works. Or am I missing someth= ing? You're missing copying of bytes. |=20 | (you should also look at the overhead of Context initialisation - HashM= ap and=20 | ConcurrentHashMap usage are by far the greatest CPU hogs in my tree at=20 | present) I have my own special Context that have a "lookaside hashmap" that holds=20 the "portal context" (as opposed to "portlet context"), so that the=20 creation of context shouldn't be very heavy. Thanks for hanging in on this discussion! Regards, Endre. |
From: Keats K. <ke...@xa...> - 2006-03-17 18:19:59
|
It's not possible to tell from your snippet, but given that you're getting an OutOfMemoryError, I would guess that you have created some sort of infinite loop, probably by including a template that includes itself, either directly or indirectly. Keats Holger King wrote: > Hi Group, > > when calling the following code snippet > > $Request.getRequestDispatcher("/test.jsp").forward($Request,$Response) > > within a WebMacro 2.0.1 template, I get the following error message: > > >WebMacro encountered an error while executing a template: > StringTemplate("cmsProvider";"## Variablen #include as template '1559' > ## Header #include as template '1562' ## Kopf mit L..."): > >> org.webmacro.PropertyException: Attempt to invoke method public >> abstract void >> javax.servlet.RequestDispatcher.forward(javax.servlet.ServletRequest,javax.servlet.ServletResponse) >> throws javax.servlet.ServletException,java.io.IOException on object >> org.apache.catalina.core.ApplicationDispatcher raised an exception: >> java.lang.OutOfMemoryError >> java.lang.OutOfMemoryError at cmsProvider:1.1 > > > Can you help me? > > Thanx in advance! > Holger King > > > |
From: Keats K. <ke...@xa...> - 2006-03-17 18:15:52
|
I haven't followed the precise details of the debate, but it seems to me that Alex is correct. That is, optimize for the non-exception case by not constructing the display name for the variable, but synchronize access to the method that does the lazy instantiation of the display name. Without synchronization it is possible that two threads (two requests for the same template) could try to create the display name at the same time with unpredictable results. In most cases, with most microprocessors, it wouldn't matter, as the processors provide stronger memory barriers than are required by the Java specs. But why take the chance, especially when the cost is minuscule? An alternative, if you *really* can't stand synchronization, would be to get rid of the member variable altogether and just have the display name computed every time it is requested. I don't see any performance benefit to this, but it would keep the state from being modified. I also agree that it is a mistake to optimize exceptional cases without any empirical evidence of a performance issue. This is a classic case of what Bruce Eckel ("Thinking in Java") calls "premature optimization". Keats Alex Twisleton-Wykeham-Fiennes wrote: >On Fri 17 March 2006 11:31, Endre Stølsvik wrote: > > >>On Mon, 13 Mar 2006, Alex Twisleton-Wykeham-Fiennes wrote: >>| On Mon 13 March 2006 12:34, Endre Stølsvik wrote: >>| > On Sun, 12 Mar 2006, Alex Twisleton-Wykeham-Fiennes wrote: >>| > | All, >>| > | >>| > | more performance tweaks, this one to the org.webmacro.engine.Variable >>| > | class. >>| > >>| > Excellent performance tuneup you're into, Alex! >>| > >>| > | - made the getVariableName() method check to see if _vname has been >>| > | initialised, and if not then build the name before returning it. >>| > | This is now synchronized as it changes the state of the object. >>| > >>| > So? >>| >>| If you don't synchronize then you could potentially have two threads >>| modifying the state of the Object simultaneously. >> >>Not unless your code allows multithreaded acccess to a _shared instance_. >>And you shouldn't, unless they absolutely have to exchange information >>through this object. >> >> > >But it *is* shared as Keats said. > > > >>| In this situation it is not the end of the world, because the >>| generation of the result is a) not that expensive, and b) not dependent >>| on other mutable properties, but I find it best to apply thread-safe >>| approaches to everything that changes state and then remove them if >>| profiling shows it to be a problem. Much better to start safe and then >>| remove redundant safety when required than to start unsafe and try and >>| make things safe when a weird multi-threading bug occurs... >> >>I don't agree: putting synchronized on every bleedin method "just because" >>is not a good strategy. If it can't be accessed by multiple threads, then >>multi-threading tactics aren't great. Beside hitting performance, they >>may potentially give you new exciting problems with deadlocks. >> >> > >It is not "just because", it is "because it reads the state of a mutable >instance variable and then changes the state of the mutable instance variable >based on the read value". > >I would be very interested if you can show me a) some performance metrics that >show that my lazy synchronized initialisation is hitting performance, and b) >how my synchronized code can generate a deadlock. I will of course then >change my implementation. > > > >>| > Is it shared across threads? >>| >>| I'd have to double check this one. It's a bit of a twisty turny passage >>| of Macro inheritance and it isn't necessarily obvious... >> >>What has inheritance to do with this? >> >>If an object that implements Macro is _shared across threads_, then _this_ >>class should do synchs on methods that change its internal state (and >>generally not using the "method syncrhonziation" paradigm - read up on >>"monitors"). But why should the general Macro-implementing objects of >>WebMacro be shared across threads?! >> >> > >Let's just assume that I don't know what I'm talking about for a moment. >Please explain at what point in the following I am on crack:- > >- Macro is an interface. >- interfaces cannot specify synchronized in their declarations according to >the java language definition. >- Variable implements Macro. >- Variable has a method that checks for an internal variable to see if it is >null and sets it if it is null. >- I would like this initialisation to only occur once so I want to synchronize >on something to achieve this. >- I can't synchronize on the variable because it is null (initially) >- I'm therefore left with the choice of synchronizing on the Object itself or >creating a second Object inside the Variable to synchronize on. > >Am I missing something? > > > >>| ps synchronizing is really not the overhead that it used to be in older >>| JVMs and it *really* makes your life easier to not have any >>| multi-threading bugs... >> >>Contended synchs are hell in any case. >> >>A synch, contended or not, have to flush all dirty cache to memory whether >>or not it is necessary. This is bad, and one should _not_ use synchs >>unless it is multithreaded accessed. >> >> > >But it *is* multithreaded accessed. And even if it wasn't, you are not sure >that it isn't or that it won't be in the future, so you write your code safe >and then optimise it when / if performance becomes an issue. > >Alex > > > |
From: Holger K. <ki...@di...> - 2006-03-17 17:08:17
|
Hi Group, when calling the following code snippet $Request.getRequestDispatcher("/test.jsp").forward($Request,$Response) within a WebMacro 2.0.1 template, I get the following error message: >WebMacro encountered an error while executing a template: StringTemplate("cmsProvider";"## Variablen #include as template '1559' ## Header #include as template '1562' ## Kopf mit L..."): >org.webmacro.PropertyException: Attempt to invoke method public abstract void javax.servlet.RequestDispatcher.forward(javax.servlet.ServletRequest,javax.servlet.ServletResponse) throws javax.servlet.ServletException,java.io.IOException on object org.apache.catalina.core.ApplicationDispatcher raised an exception: java.lang.OutOfMemoryError >java.lang.OutOfMemoryError at cmsProvider:1.1 Can you help me? Thanx in advance! Holger King |
From: Alex Twisleton-Wykeham-F. <al...@fi...> - 2006-03-17 12:03:38
|
On Fri 17 March 2006 11:31, Endre St=C3=B8lsvik wrote: > On Mon, 13 Mar 2006, Alex Twisleton-Wykeham-Fiennes wrote: > | On Mon 13 March 2006 12:34, Endre St=C3=B8lsvik wrote: > | > On Sun, 12 Mar 2006, Alex Twisleton-Wykeham-Fiennes wrote: > | > | All, > | > | > | > | more performance tweaks, this one to the org.webmacro.engine.Variab= le > | > | class. > | > > | > Excellent performance tuneup you're into, Alex! > | > > | > | - made the getVariableName() method check to see if _vname has been > | > | initialised, and if not then build the name before returning it.=20 > | > | This is now synchronized as it changes the state of the object. > | > > | > So? > | > | If you don't synchronize then you could potentially have two threads > | modifying the state of the Object simultaneously. > > Not unless your code allows multithreaded acccess to a _shared instance_. > And you shouldn't, unless they absolutely have to exchange information > through this object. But it *is* shared as Keats said. > | In this situation it is not the end of the world, because the > | generation of the result is a) not that expensive, and b) not dependent > | on other mutable properties, but I find it best to apply thread-safe > | approaches to everything that changes state and then remove them if > | profiling shows it to be a problem. Much better to start safe and then > | remove redundant safety when required than to start unsafe and try and > | make things safe when a weird multi-threading bug occurs... > > I don't agree: putting synchronized on every bleedin method "just because" > is not a good strategy. If it can't be accessed by multiple threads, then > multi-threading tactics aren't great. Beside hitting performance, they > may potentially give you new exciting problems with deadlocks. It is not "just because", it is "because it reads the state of a mutable=20 instance variable and then changes the state of the mutable instance variab= le=20 based on the read value". I would be very interested if you can show me a) some performance metrics t= hat=20 show that my lazy synchronized initialisation is hitting performance, and b= )=20 how my synchronized code can generate a deadlock. I will of course then=20 change my implementation. > | > Is it shared across threads? > | > | I'd have to double check this one. It's a bit of a twisty turny passage > | of Macro inheritance and it isn't necessarily obvious... > > What has inheritance to do with this? > > If an object that implements Macro is _shared across threads_, then _this_ > class should do synchs on methods that change its internal state (and > generally not using the "method syncrhonziation" paradigm - read up on > "monitors"). But why should the general Macro-implementing objects of > WebMacro be shared across threads?! Let's just assume that I don't know what I'm talking about for a moment. =20 Please explain at what point in the following I am on crack:- =2D Macro is an interface. =20 =2D interfaces cannot specify synchronized in their declarations according = to=20 the java language definition. =20 =2D Variable implements Macro. =2D Variable has a method that checks for an internal variable to see if it= is=20 null and sets it if it is null. =2D I would like this initialisation to only occur once so I want to synchr= onize=20 on something to achieve this. =2D I can't synchronize on the variable because it is null (initially) =2D I'm therefore left with the choice of synchronizing on the Object itsel= f or=20 creating a second Object inside the Variable to synchronize on. Am I missing something? > | ps synchronizing is really not the overhead that it used to be in older > | JVMs and it *really* makes your life easier to not have any > | multi-threading bugs... > > Contended synchs are hell in any case. > > A synch, contended or not, have to flush all dirty cache to memory whether > or not it is necessary. This is bad, and one should _not_ use synchs > unless it is multithreaded accessed.=20 But it *is* multithreaded accessed. And even if it wasn't, you are not sur= e=20 that it isn't or that it won't be in the future, so you write your code saf= e=20 and then optimise it when / if performance becomes an issue. Alex |
From: Alex Twisleton-Wykeham-F. <al...@fi...> - 2006-03-17 11:51:33
|
On Fri 17 March 2006 11:23, Endre St=F8lsvik wrote: > On Mon, 13 Mar 2006, Alex Twisleton-Wykeham-Fiennes wrote: > | > I do it using _a new_ FastWriter with a temporary backing, then if > | > everything went right, I put the result to the FastWriter. > | > | Do you use a seperate Context for each portlet as well? > > Yes. > But assuming that the Portlets aren't _pure_ evil, this would have been a > big thing: I could just have recreated the initial state before each > rendering, by using a "weird-long-named" context-var for "my state", > hoping that the corelet wouldn't intentially mess things up. > > But I do make a new Context, due to this concern. > > | > This temporary backing paradigm obviously isn't the best, and a > | > mark/reset/flush paradigm would be much better for my part. > | > | I can see where you are coming from on this, but it is very hard to sta= te > | what the side effects of flushing the FastWriter early and / or rolling > | it back to an earlier state. > > Why is that? This seems completely illogical to me, I can't see at all > where you're coming from. > > If I still make new Contexts, and you understand that each portlet is "on > its own" (with a logical separate context too), and if I don't commit > bytes to the browser-stream before flush, then "rolling back" is _exactly_ > the same as ditching the buffer, _as I do now_. I understand exactly what you have at the moment, and I understand what is= =20 being suggested, but let me just recap for a moment:- =2D you have a series of portlets. Currently you are rendering these by=20 creating a new Context and a new FastWriter, doing all the work and then=20 dropping the contents of the FastWriter (which will either contain your=20 portlet or your error report) into the master FastWriter. =2D you are proposing to save the creation time of a new FastWriter by usin= g the=20 master FastWriter for the global template page and resetting it as necessar= y=20 to handle the consequences (I think the use of flush in your mark/reset/flu= sh=20 is maybe what is confusing because flushing by definition drops the content= s=20 of the FastWriter out to the output stream which is probably not what you=20 mean). Now, just for a moment in order to play devils advocate: supposing that we= do=20 have this #flush command that Keats mentioned, and suppose one of your=20 portlet implementors executes #flush inside one of your portlet and the byt= es=20 (both before and after your mark) are flushed out to the output stream. Yo= u=20 then try and do a reset, but the reset point along with all the data before= =20 and after it has already been sent down-stream. Personally, I think that you already have a nicely encapsulated safe struct= ure=20 for your portlets with a dedicated Context and a dedicated FastWriter for=20 each portlet. Error failure is encapsulated and you don't drop the result = of=20 your parsing / error catching out to your master FastWriter until it is=20 completed. If you are concerned about the overhead of generating lots (1 p= er=20 portlet) of new FastWriter instances, then I would use just one FastWriter= =20 that is shared between all of your Portlets, and your sequence would be:- =2D create Portlet FastWriter =2D foreach portlet in portlets - create new Portlet Context - reset Portlet FastWriter try { - render portlet with Portlet Context to Portlet FastWriter } catch (exception) { - reset FastWriter - render error with Portlet Context to Portlet FastWriter } - write Portlet FastWriter to Servlet FastWriter } =2D write Servlet FastWriter to OutputStream Now, you still have all of your encapsulation, your rollbacks work, you are= =20 creating at most one FastWriter beyond where you are, and it really doesn't= =20 matter what happens inside the rendering loop and you don't need to make an= y=20 functional changes to how the FastWriter works. Or am I missing something? (you should also look at the overhead of Context initialisation - HashMap a= nd=20 ConcurrentHashMap usage are by far the greatest CPU hogs in my tree at=20 present) <snip> Alex |
From: <Web...@St...> - 2006-03-17 11:32:47
|
On Mon, 13 Mar 2006, Keats Kirsch wrote: | Endre St=F8lsvik wrote: |=20 | > On Sun, 12 Mar 2006, Alex Twisleton-Wykeham-Fiennes wrote: | >=20 | > | All, | > | | more performance tweaks, this one to the org.webmacro.engine.Vari= able | > class. | >=20 | > Excellent performance tuneup you're into, Alex! | >=20 | > | - made the getVariableName() method check to see if _vname has been= | | > initialised, and if not then build the name before returning it. Thi= s is | > now | synchronized as it changes the state of the object. | >=20 | > So? | >=20 | > Is it shared across threads? | > =20 | The answer is yes, as we were so rudely reminded when the dynamic #incl= ude bug | was discovered recently. Compiled template instances are cached and ma= y be | shared by multiple threads. That templates are shared, is kinda rather obvious - they are cached. Tha= t=20 they have som much _modifiable_ internal state isn't necessarily that=20 obvious to me. Endre. |
From: <Web...@St...> - 2006-03-17 11:31:44
|
On Mon, 13 Mar 2006, Alex Twisleton-Wykeham-Fiennes wrote: | On Mon 13 March 2006 12:34, Endre St=F8lsvik wrote: | > On Sun, 12 Mar 2006, Alex Twisleton-Wykeham-Fiennes wrote: | > | All, | > | | > | more performance tweaks, this one to the org.webmacro.engine.Variab= le | > | class. | > | > Excellent performance tuneup you're into, Alex! | > | > | - made the getVariableName() method check to see if _vname has been | > | initialised, and if not then build the name before returning it. T= his is | > | now synchronized as it changes the state of the object. | > | > So? |=20 | If you don't synchronize then you could potentially have two threads mo= difying=20 | the state of the Object simultaneously. Not unless your code allows multithreaded acccess to a _shared instance_.= =20 And you shouldn't, unless they absolutely have to exchange information=20 through this object. | In this situation it is not the end of the world, because the=20 | generation of the result is a) not that expensive, and b) not dependent= =20 | on other mutable properties, but I find it best to apply thread-safe=20 | approaches to everything that changes state and then remove them if=20 | profiling shows it to be a problem. Much better to start safe and then= =20 | remove redundant safety when required than to start unsafe and try and=20 | make things safe when a weird multi-threading bug occurs... I don't agree: putting synchronized on every bleedin method "just because= "=20 is not a good strategy. If it can't be accessed by multiple threads, then= =20 multi-threading tactics aren't great. Beside hitting performance, they=20 may potentially give you new exciting problems with deadlocks. |=20 | > Is it shared across threads? |=20 | I'd have to double check this one. It's a bit of a twisty turny passag= e of=20 | Macro inheritance and it isn't necessarily obvious... What has inheritance to do with this? If an object that implements Macro is _shared across threads_, then _this= _=20 class should do synchs on methods that change its internal state (and=20 generally not using the "method syncrhonziation" paradigm - read up on=20 "monitors"). But why should the general Macro-implementing objects of=20 WebMacro be shared across threads?! |=20 | Alex |=20 | ps synchronizing is really not the overhead that it used to be in older= JVMs=20 | and it *really* makes your life easier to not have any multi-threading=20 | bugs... Contended synchs are hell in any case. A synch, contended or not, have to flush all dirty cache to memory whethe= r=20 or not it is necessary. This is bad, and one should _not_ use synchs=20 unless it is multithreaded accessed. This is the same reason why the=20 Collections framework was made unsynched (as opposed to the idiotic=20 synched Vectors and Hashtable), and that _finally_ they've made a new=20 StringBuffer (StringBuilder) that is unsynched (can you _believe_ that=20 StringBuffer is synched? I was shocked to find out..). Endre. |