268
I Use This!
Very Low Activity

News

Analyzed 1 day ago. based on code collected 3 days ago.
Posted over 14 years ago
Recently we got a bug report about the performance of Windsor when registering large number of components (thousands). I decided to sit down and investigate this, and found out something that was troublesome. Internally, registering a component ... [More] would trigger a check for all registered components that are waiting for a dependency. If you had a lot of components that were waiting for dependency, registering a new component degenerated to an O(N^2) operation, where N was the number of components with waiting dependencies. Luckily, there was no real requirement for an O(N^2) operation, and I was able to change that to an O(N) operation. Huge optimization win, right? In numbers, we are talking about 9.2 seconds to register 500 components with no matching dependencies. After the optimization, we dropped that to 500 milliseconds. And when we are talking about larger number of components, this is still a problem. After optimization, registering 5,000 components with no matching dependencies took 44.5 seconds. That is better than before (where no one has the patience to try and figure out the number), but I think we can improve up it. The problem is that we are still paying that O(N) cost for each registration. Now, to suppose systems that already uses Windsor, we can’t really change the way Windsor handle registrations by default, so I came up with the following syntax, that safely change the way Windsor handles registration: var kernel = new DefaultKernel();using (kernel.OptimizeDependencyResolution()){ for (int i = 0; i < 500; i++) { kernel.AddComponent("key" + i, typeof(string), typeof(string)); }} Using this method, registering 5,000 components drops down to 2.5 seconds. I then spent additional time finding all the other nooks and crannies where optimizations hid, dropping the performance down to 1.4 seconds. Now, I have to say that this is not linear performance improvement. Registering 20,000 components will take about 25 seconds. This is not a scenario that we worry over much about. The best thing about the non linear curve is that for a 1,000 components, which is what we do care about, registration takes 240 milliseconds. Most applications don’t get to have a thousand components, anyway. There are also other improvements made in the overall runtime performance of Windsor, but those would be very hard to notice outside of a tight loop. [Less]
Posted over 14 years ago
Pysor Series Using IronPython to configure Castle Windsor I : the basic functionality Using IronPython to configure Castle Windsor II : parameters and references Using IronPython to configure Castle Windsor III : arrays and lists In the first two ... [More] articles I introduced Pysor, the Castle Windsor configuration tool using IronPython. Now I have added some exciting functions to exploit [...] [Less]
Posted over 14 years ago
One thing that may be overlooked sometimes (I certainly did) is the ability of ActiveRecord to not only bind to properties but also to instance fields (yes, even private ones). This little feature came in very handy when I was looking for a way to persist a class based enumeration. I’ll tell you why in [...]
Posted over 14 years ago
James Curran pointed me at one interesting flaw with my implementation of the DefaultValueAttribute for MonoRail I blogged about some weeks ago. This tipped me off to actually read the MonoRail code to find out how exactly MonoRail selects what overload of a ActionMethod to call. MonoRail’s approach is as simple as it is brilliant, and [...]
Posted over 14 years ago
This was intended to be a two-part article. It was just after I published the original article, I noticed that I’d left out a large part of ViewComponentEx. We continue….. protected bool RenderOptionalSection(string section) protected bool ... [More] RenderOptionalSection(string section, string defaultText) Renders the named section of a block component – if the section is present. If not, it just silently returns. The second overload lets you provide some text to be rendered, if that section isn’t given: RenderOptionalSection("tablestart", “<table>”) Returns true if this section was rendered; false, if the section was present. This seems like a very simple method (and it is), but if your component has a number of different sections for styling (such as the SmartGridViewComponent, which has 18!), this can do wonders to streamline your code. void RenderComponent<VC>(params string[] componentParams) where VC : ViewComponentEx, new(); void RenderComponent<VC>(IDictionary componentParams) where VC : ViewComponentEx, new(); void RenderComponent(ViewComponentEx component, params string[] componentParams); void RenderComponent(ViewComponentEx component, IDictionary componentParams); This implement, with a slightly different syntax, a technique originally devised by Joey Beninghove. The idea is to make a ViewComponent which is composite of several other VCs. The basic syntax is RenderComponent<LinkSubmitButtonComponent>("linkText=Search", string.Format("formToSubmit={0}", searchFormName)); However, the various overloads allow using an already exist component object, and/or an already built dictionary of options. Also include in the source file is the class ViewComponentUsingSiteMap which, like ViewComponentEx, is an abstract base use for creating ViewComponents, but I’ll hold off discussing that until I ready to talk about the VCs the derive from it. Share this post: Email it! | bookmark it! | digg it! | reddit! [Less]
Posted over 14 years ago
I’ve been rewriting my website, njtheater.com, (very slowly) as a Castle MonoRail application. Along the way, I’ve written a number of ViewComponent and other elements. Many of these were of general use, so I’ve added them to the CastleContib ... [More] project, and documented them in the using.castleproject.org wiki. Two problem there: First, some of the items I wrote don’t fit into an exist category in CastleContrib (There’s one for ViewComponents, which I’ve stick a filter into, but putting a Controller base class there seemed wrong). Second, CastleContrib & using.castleproject.org seem to be somewhat of a black hole. No one seems to look there for information about the Castle Project (which is kind of a shame, since that’s exactly it’s purpose). On the other hand, blogs posts about Castle are turning up everywhere. We’ve even now got an aggregated blog feed specific to Castle. So, I figured, I start using my blog to talk about what I’ve written. In fact, one article I discovered on that aggregator was Andy Pike’s “Integrating Gravatar with Castle MonoRail” inwhich he discusses a Helper object for Monorail which creates Gravatars for use’s email addresses. It was written last January. The only thing is, I’ve written (and added to CastleContrib) a Gravatar component three months earlier. That was going to be the topic of my first MonoRail blog post (and I will be my second), but first, I figure I should talk about the base class I once for all my ViewComponents, which I’ve given the rather imaginative name of ViewComponentEx. ViewComponentEx derives from ViewComponent, and can be used as a “drop-in” replacement for it, as the base class for your ViewComponents. It provides a number of simple methods to help building ViewComponents. void ConfirmSectionPresent(string section); Throws an exception if the given section is not present. string GetSectionText(string section); Get the text of a section as a string. string GetBodyText(); Get the text of the body of a block component (without section) void RenderTextFormat(string format, params object[] args); Renders the text, formatted. Just like String.Format() string GetParamValue(string key, string defaultValue); bool GetParamValue(string key, bool defaultValue); E GetParamValue(string key, E defaultValue) where E : struct; Gets a parameter value, with a default. Overloaded to handle string, boolean, or Enum value. Castle.Core.Logging.ILogger Logger { get; set; } A property for the system Logger. Automatically wired by Windsor, if active and a Logger is defined in the container. Default to NullLogger, otherwise. string MakeUniqueId(string prefix); Makes an unique id. The given prefix is prepended to the generated number. The ID isn't actually guaranteed to be unique (which would require using all 32 digits of the guid). But this produce ids sufficiently distinctive to generate multiple controls on a page.   Code available here: ViewComponentex.cs Share this post: Email it! | bookmark it! | digg it! | reddit! [Less]
Posted over 14 years ago
Pysor Series Using IronPython to configure Castle Windsor I : the basic functionality Using IronPython to configure Castle Windsor II : parameters and references Using IronPython to configure Castle Windsor III : arrays and lists In the last article ... [More] I introduced a small Castle Windsor configuration tool using IronPython. This tool enabled us to add service implementation in an [...] [Less]
Posted almost 15 years ago by [email protected] (mausch)
I generally advise to keep the IoC container out of the tests, but sometimes it is a convenient tool to have. Take for example the auto-mocking container concept. It's just too useful so I make an exception to the previous rule sometimes. Here's ... [More] another use for a container in a test: a profiler. All IoC containers have some proxying abilities (or rather, they delegate to one of the proxying libraries), which can be leveraged to build a basic profiler. A profiler is especially useful in integration tests where there's something that's taking too much time but you can't put your finger on the culprit simply because there are too many components involved. A real-world example: an application which uses SolrNet was taking too long when getting lots of documents from Solr. There was nothing weird in Solr's log so it was a client issue. Let's profile it! Setting up the profiler We create a ProfilingContainer and add all the components we want to profile: IWindsorContainer container = new ProfilingContainer(); container.AddComponent<ISolrDocumentResponseParser<Document>, SolrDocumentResponseParser<Document>>(); container.AddComponent<ISolrResponseParser<Document>, ResultsResponseParser<Document>>("resultsParser"); container.AddComponent<IReadOnlyMappingManager, AttributesMappingManager>(); container.Register(Component.For<ISolrQueryResultParser<Document>>().ImplementedBy<SolrQueryResultParser<Document>>() .ServiceOverrides(ServiceOverride.ForKey("parsers").Eq(new[] { "resultsParser" }))); container.AddComponent<ISolrFieldParser, DefaultFieldParser>(); container.AddComponent<ISolrDocumentPropertyVisitor, DefaultDocumentVisitor>(); Adding code to profile We add the code that exercises the components: var parser = container.Resolve<ISolrQueryResultParser<Document>>(); for (int i = 0; i < 1000; i++) { parser.Parse(responseXMLWithArrays); } Getting the actual profile data Finally, we get the profile data: Node<KeyValuePair<MethodInfo, TimeSpan>> rawProfile = container.GetProfile(); This returns a tree of method calls, each with its logged duration. We just want a list of aggregated durations, so first we flatten the tree: IEnumerable<KeyValuePair<MethodInfo, TimeSpan>> profile = Flatten(rawProfile); And now we can query and write the profile: var q = from n in profile group n.Value by n.Key into x let kv = new { method = x.Key, count = x.Count(), total = x.Sum(t => t.TotalMilliseconds)} orderby kv.total descending select kv; foreach (var i in q) Console.WriteLine("{0} {1}: {2} executions, {3}ms", i.method.DeclaringType, i.method, i.count, i.total); Which prints something like this (prettified): Method Executions Total own time AttributesMappingManager.GetFields(Type) 21000 2803.23ms DefaultDocumentVisitor.Visit(Object, String, XmlNode) 10000 432.19ms DefaultFieldParser.Parse(XmlNode, Type) 10000 122.77ms SolrQueryResultParser<Document>.Parse(String) 1000 93.52ms DefaultFieldParser.CanHandleType(Type) 10000 44.71ms SolrDocumentResponseParser<Document>.ParseResults(XmlNode) 1000 43.11ms ResultsResponseParser<Document>.Parse(XmlDocument, SolrQueryResults<Document>) 1000 30.28ms DefaultFieldParser.CanHandleSolrType(String) 10000 23.78ms   Analyzing the profile Well, it's obvious that AttributesMappingManager.GetFields() is to be blamed here, it's taking a lot of time... which is only logical since it uses a lot of reflection... But wait a minute, I already thought about that when I wrote that MemoizingMappingManager (which is a memoizer decorator for the AttributesMappingManager)... only I forgot to add it to the container! Fixing and re-running the profile After adding the MemoizingMappingManager, the profile comes out like this: Method Executions Total own time DefaultDocumentVisitor.Visit(Object, String, XmlNode) 10000 358.64ms SolrQueryResultParser<Document>.Parse(String) 1000 166.64ms DefaultFieldParser.Parse(XmlNode, Type) 10000 87.13ms MemoizingMappingManager.GetFields(Type) 21000 50.5ms DefaultFieldParser.CanHandleType(Type) 10000 42.03ms SolrDocumentResponseParser<Document>.ParseResults(XmlNode) 1000 34.93ms ResultsResponseParser<Document>.Parse(XmlDocument, SolrQueryResults<Document>) 1000 30.83ms DefaultFieldParser.CanHandleSolrType(String) 10000 22.22ms AttributesMappingManager.GetFields(Type) 1 19.82ms   Conclusion This cheap profiler has a number of caveats: Since it works by adding a DynamicProxy interceptor to everything, it can only profile interceptable classes and methods managed by Windsor. Times should be taken with a grain of salt. Based on a couple of unscientific tests, it can introduce an error of 10ms (on my machine), rendering a 10ms measured time useless. I'd only use these times for a qualitative comparison. There's a reason why there's a specific .Net profiling API. Multithreading: each thread will get its own interceptor, so each thread gets its own profile. What I just described is not really a test. There is nothing asserted, it can't pass or fail. The "test" here is just a means to run the profile. It should be [Ignore]d. All in all, I found this to be quite useful. ProfilingContainer is just a thin wrapper around WindsorContainer that adds a ProfilerFacility, which in turn sets up a ProfilingInterceptor. So you could, for example, add the ProfilingInterceptor to your application container with a per-web-request lifestyle and code a HttpModule to profile an entire http request. Code is here. Sample profile shown in this post is here. [Less]
Posted almost 15 years ago
I believe the simplest way to store binary data is to just put in the database. Whenever I’ve agreed to throw data to a disk I’ve had issues with deployment, administration or disaster recovery. Simply put: Once you have a dependency from your database to your file system, you no longer have the luxury of [...]
Posted almost 15 years ago
Pysor Series Using IronPython to configure Castle Windsor I : the basic functionality Using IronPython to configure Castle Windsor II : parameters and references Using IronPython to configure Castle Windsor III : arrays and lists Castle Windsor is a ... [More] very popular IoC container in the .Net world. Like almost all other containers it can be configured using either a [...] [Less]