In my previous post, I mentioned how my new blog is currently powered by
Subtext -- or rather my own (slightly modified)
version of Subtext 2.5. I also noted that Subtext wasn't my first choice when selecting
a blogging solution for the new TechnologyToolbox.com site.
BlogEngine.NET or dasBlog?
Actually, I started out using BlogEngine.NET.
Initially, I looked at both dasBlog and BlogEngine.NET.
dasBlog made the short list because I've seen it in use on
Scott Hanselman's blog for a number
of years and he seems quite happy with the performance, stability, and feature set.
He even contributes an occasional bug fix for dasBlog every now and then (e.g. changesets
55621
and
50527) which gave me a "warm and fuzzy" feeling during the due diligence process
of selecting a blogging solution.
The problem with dasBlog is that it appears to be "dead" from a development perspective
-- meaning nobody seems to be actively working on it. If you look at the main dasBlog
site (http://dasblog.info) you will see that
it still refers to the March 16th 2009 version as the latest release -- and yet
when you look at the corresponding CodePlex
project, you can see dozens of bug fixes and enhancements have been checked
in since that time. Therefore I turned my attention from dasBlog and started focusing
on BlogEngine.NET instead.
I really liked what I saw in BlogEngine.NET. The solution is very "polished"
(unlike a number of other open source blogging solutions out there), appears to
be very extensible, and -- unlike dasBlog -- is actively being worked on by the
development team. It supports all of the core features that I considered "must haves"
for the TechnologyToolbox.com blog, and it was very easy to install and configure.
It also supports BlogML for importing posts (which was originally a "nice-to-have"
on my list -- although, in retrospect, I would now consider this a "must have" instead).
Consequently, I decided to go with BlogEngine.NET and proceeded to create a utility
to migrate my blog content from my old
MSDN blog. That's when I discovered a showstopper...
After migrating the roughly 300 posts from my MSDN blog (running on the Telligent
Community platform) into my new BlogEngine.NET-based blog, I noticed some significant
performance issues.
Note that the default configuration of BlogEngine.NET does not require a SQL
Server database. Instead blog posts are stored as individual XML files and accessed
through a provider that encapsulates the underlying storage mechanism.
Suspecting the XML storage implementation to be the source of the performance
problem, I spent a few minutes creating a SQL Server database and switching from
the XmlBlogProvider to the
DbBlogProvider
-- and subsequently migrated my historical content into the database. I fully expected
this to resolve the scalability issue I discovered shortly before.
Unfortunately it did not.
After spending about a half hour walking through BlogEngine.NET in the debugger,
I discovered that the source of the problem was not in the underlying blog provider
(i.e. XmlBlogProvider or DbBlogProvider), but
rather in the service layer "above" the provider.
It turns out that BlogEngine.NET caches all of your blog posts in memory -- regardless
of whether you choose to store them in XML files or in a SQL Server database. And
it's not just the post summary information that is cached in memory. Rather it's
the entire content of each and every post.
Specifically, in BlogEngine.NET all of the post content is stored in a static
list -- which makes it even worse than if this same approach were implemented using
the ASP.NET caching infrastructure. If the ASP.NET cache were used, then at least
the underlying platform could do its job of effectively managing the memory usage
of the application (assuming the full content of each post was cached individually).
When I discovered this, I did some quick searching on the BlogEngine.NET forums
and found several other people complaining about the same issue. I also found references
to BlogEngine.NET deployments with many more blog posts than I currently have, which
made me wonder how they were able to cope with what I consider to be a fundamental
flaw in the architecture of BlogEngine.NET.
The reason, it turns out, depends entirely on what your deployment architecture
looks like. In other words, are you running BlogEngine.NET on a dedicated server
with multiple gigabytes of RAM? If that's the case, then the approach taken by the
BlogEngine.NET development team isn't really an "architectural flaw" at all -- rather
they are simply taking advantage of the "memory is cheap these days" mantra and
it will take a lot of blog posts to consume even 1GB of memory.
However what if, like me, you are running in a shared hosting environment? In
that case, the "memory is cheap" excuse no longer holds true, because the hosting
provider (e.g. WinHost) needs to run many different websites on a single server.
If your application has a large memory footprint, then it is not a good candidate
for shared hosting. [Note that I never saw anything from WinHost regarding how much
memory consumption would be considered a problem. Rather my gut told me that if
I continued with BlogEngine.NET then eventually I would hear from the WinHost support
folks telling me I either need to consume less memory or move to a dedicated hosting
plan instead.]
Thus began my search for another blogging solution.
After some more looking around, I discovered a few other potential candidates:
Oxite
Note that I didn't spend any significant time looking at Oxite, since CodePlex
clearly states it is no longer being worked on. However, it did lead me to the Orchard
CMS project which looked very promising...at first.
Orchard CMS
It's worth emphasizing that Orchard is a Content Management System -- not just
a blog engine. In other words, while it includes blogging functionality "out-of-the-box",
it also provides the core infrastructure for many other types of website content.
When I discovered that Orchard is powering the blog for the renowned
John Papas, I thought surely this would be the
just the cure for my BlogEngine.NET woes. Consequently, I downloaded Orchard, installed
it on one of my development VMs, and proceeded to setup a test blog with some sample
content from my old MSDN blog.
After my experience with BlogEngine.NET, you can imagine that I was feeling a
little "gun shy" about free, open source applications for blogging. As such I quickly
started looking at the underlying architecture of Orchard, rather than how it appeared
on the surface from the administrator and blog author perspectives.
Like BlogEngine.NET, Orchard appears very "polished" and was a breeze to setup.
Orchard is also very extensible.
Unfortunately, I quickly discovered a couple of issues with Orchard that left
me feeling a little queasy.
The first is what appears to be a rather obvious bug that is described in a question
posted on Stack Overflow:
How can I set the permissions for blogs in Orchard CMS?
The second issue is related to the fundamental architecture of Orchard. When
I used SQL Server Profiler to inspect the database calls for one of my sample blog
pages (as described in
one of my previous posts), I observed over 40 separate round-trips to the database
just to render a single page. [Note that I am going off memory here from
a couple of months ago, so I could be wrong about the number -- but I seem to recall
something in the neighborhood of 42-44 round-trips to SQL Server.]
In my opinion, the Orchard team has made a substantial tradeoff in optimization
(i.e. minimizing the number of database calls required to render a page) in order
to achieve a highly componentized architecture and what they call "UI composition"
(e.g. content item → content type → content part). While I admire the
ultimate goals and flexibility in the Orchard architecture, it seems a little too
"ivory tower" to me and I wonder how Orchard scales in real world deployments.
By comparison, SharePoint typically requires only one or two database round-trips
to render a page (once the site is warmed up, of course). Note that in SharePoint-Land,
a single round-trip to SQL Server often includes multiple stored procedure calls
or T-SQL statements batched together. The key point to understand is that SharePoint
tries to fetch everything it needs from the database to render a single page using
a very small number of round-trips to SQL Server, because the SharePoint team --
like me -- believes the key to scaling massively is to minimize your "off-the-box"
calls.
Based on what I saw in my cursory examination of the Orchard architecture, it
seems like Orchard would require substantial rework in order to batch multiple calls
to the database into significantly fewer round-trips to SQL Server.
Consequently, I moved on to looking at another CMS solution that includes blogging
functionality, namely Umbraco.
Umbraco
Umbraco is relatively easy to install and configure, but I discovered some issues
when you want to run it in isolation within your site. For example, as I mentioned
in my previous post, I was looking for a blogging solution to serve content from
the /blog folder of TechnologyToolbox.com while other areas of
the site are served from a different ASP.NET application.
In this configuration, I encountered an error similar to the one described in
the following issue:
Error after installing blog
Fortunately, a little digging around led to the corresponding fix:
xslt assumes Blog is in root
However, the more I looked at Umbraco, the more I felt like it was too complex
for what I was looking for. The more I dug into Umbraco, the more I thought about
how much time I would need to invest in learning yet another CMS solution. Since
SharePoint is one of my core competencies, I honestly don't see myself recommending
Umbraco over SharePoint for the size of companies that I tend to work with.
Right about the time I started looking into customizing the "master page" in
Umbraco, I decided to once again pull the plug.
At this point, I was getting quite frustrated in my search for a replacement
to my original choice of BlogEngine.NET. In fact, I even thought about writing my
own blogging solution (albeit with minimal functionality).
Fortunately, that's when I discovered Subtext.
Subtext
If you've ever caught yourself throwing your hands in the air and declaring
that you're going to write your own blogging engine, then Subtext is for
you.
When I read these words, I got goose bumps. Okay...not really...but they certainly
did resonate with me based on my recent experience.
Fortunately, Subtext was a breeze to install and I don't recall hitting any snags
right away (unlike my experience with Orchard and Umbraco). More importantly, however,
after looking at the underlying architecture of Subtext, and "sniffing" the database
traffic using SQL Server Profiler, I had a much better feeling about it than I did
with any of the other blogging solutions I considered using.
Subtext does a fair amount of caching, but it does so in a way that I consider
to be much "smarter" than BlogEngine.NET -- and the fact that it actually does caching
seems to make it a more logical choice than Orchard -- at least at this point in
time. [That's not meant to bash the Orchard development team. I sincerely hope that
in the near future, they turn their attention to optimizing performance and scalability.]
Subtext is definitely not as "polished" as BlogEngine.NET or Orchard from a UI
perspective (and to be honest, you can tell that Phil
doesn't place a great deal of value on the look-and-feel of the blog admin pages).
Nevertheless, the core functionality appears to be very solid.
Are there bugs in Subtext? Sure...there are bugs in every piece of software
out there.
Did I encounter any issues with Subtext while implementing it on TechnologyToolbox.com?
Well, yes, as a matter of fact I did.
Fortunately, though, it didn't take very long to get up-to-speed on the inner
workings of Subtext, and I was able to make the necessary tweaks that I needed along
the way.
I'll explain more about those "tweaks" in subsequent posts.