CNBlogsDottext Beta2 的性能杀手之SiteCategory.ascx
2007-04-16 11:53 无常 阅读(2912) 评论(1) 编辑 收藏 举报如果你在使用CNBlogsDottext Beta2代码搭建BLOG站点,如果你的打开首页时每次都很慢,那就继续往下看。
~/AggSite/SiteCategory.ascx就是首页左边第二栏的“网站分类”控件,代码文件是~/AggSite/SiteCategory.ascx.cs。
http://wuchang.cnblogs.com
qq:3263262
现在来看看这个控件究竟是如何成为性能杀手的。
先来看看.ascx部分代码
<asp:Repeater ID="CategoryLevel1" runat="server">
<ItemTemplate>
<li>
<asp:HyperLink runat="server" ID="Link" NavigateUrl='<%# GetUrl(DataBinder.Eval(Container.DataItem,"CategoryID",null)) %>'>
<%# CheckTitle(DataBinder.Eval(Container.DataItem,"Title",null),DataBinder.Eval(((RepeaterItem)Container).DataItem,"CategoryID",null)) %>
</asp:HyperLink>
<asp:HyperLink runat="server" ID="RssLink" Text="(rss)" NavigateUrl='<%# GetRssUrl(DataBinder.Eval(((RepeaterItem)Container).DataItem,"CategoryID",null)) %>' />
</li>
.
注意绑定代码中使用了CheckTitle函数,接下来看看.cs 代码。
{
CategoryLevel1.DataSource=Config.GetSiteBlogConfigCollection();
CategoryLevel1.DataBind();
}
在页面加载时调用了Config.GetSiteBlogConfigCollection()获取网站分类:
{
string dataFile=System.Web.HttpContext.Current.Server.MapPath("~/SiteBlogConfig.config");
return (SiteBlogConfigCollection)Util.SerializationHelper.Load(typeof(SiteBlogConfigCollection),dataFile);
}
杀手1现形:
这里在每次首页加载的时候都要加载.config,然后返回反序列化得到的对象。众所周知序列化和反序列化性能是很低的,而这里每次页面加载都重复做一次,对性能的影响就不可不计了。
接下来看刚才提到的CheckTitle()方法:
{
if(Config.Settings.CategoryDepth==2)
{
return title;
}
SiteBlogConfig config=Config.GetSiteBlogConfigByCategoryID(int.Parse(CategoryID));
if(config!=null)
{
title+=string.Format("({0}/{1})",GetRowsCount(true,config).ToString(),GetRowsCount(false,config).ToString());
}
return title;
}
这个方法返回的类似“最新评论区(0/21033) ”的字符串。
杀手2现形:
在这个方法中再次再现调用GetSiteBlogConfigByCategoryID() -> GetSiteBlogConfigCollection() ->GetSiteBlogConfigCollection()!这个方法可是在每次OnItemDataBound是都调用的呀,也就是说如果有10个网站分类,那么每次打开页面时在这里都重复10次反序列化"~/SiteBlogConfig.config"这个配置文件。
队此之外,这个访求中还2次调用GetRowsCount()方法,这个方法代码如下:
{
EntryQuery query = new EntryQuery();
query.PostType = PostType.BlogPost;
query.PostConfig = PostConfig.IsActive|PostConfig.IsAggregated;
if(IsToday)
{
DateTime now=DateTime.Now;
DateTime StartDate=new DateTime(now.Year,now.Month,now.Day,0,0,0,0);
query.StartDate=StartDate;
}
query=(EntryQuery)Dottext.Framework.Util.Globals.BuildEntryQuery(query,config);
return Entries.GetEntryCount(query);
}
此方法返回指定分类的文章数,如果IsToday=true,则只返回分类当天的文章数。最后一行调用
Entries.GetEntryCount(query);跟踪这个方法,在FrameWork项目Entries.cs中:{
return DTOProvider.Instance().GetEntryCount(query);
}
{
return GetReader("blog_GenericGetEntriesCount_10",EntryQueryParameters(query));
}
if(@CategoryID is not null)
Begin
--we will filter by categoryID. Should we also filter by date?
if(@StartDate is null)
Begin
-- No Date Filter
SELECT
count(bc.[ID]) as Count
FROM
blog_Content bc with(nolock)
INNER JOIN blog_Links bl with(nolock) on bc.ID = bl.PostID
INNER JOIN blog_Config bcc with(nolock) on bc.BlogID = bcc.BlogID and bcc.IsAggregated = 1
WHERE
bc.PostConfig & @PostConfig = @PostConfig
and bc.PostType | @PostType = @PostType
and bl.CategoryID = @CategoryID
End
Else
Begin
--Filter by CategoryID and Date.
--If we only have a start date and no stop date, add 24 hours to to stopdate
if(@StartDate is not null and @StopDate is null)
Set @StopDate = DateAdd(day,1,@StartDate)
-- No Date Filter
SELECT
count(bc.[ID]) as Count
FROM
blog_Content bc with(nolock)
INNER JOIN blog_Links bl with(nolock) on bc.ID = bl.PostID
INNER JOIN blog_Config bcc with(nolock) on bc.BlogID = bcc.BlogID and bcc.IsAggregated = 1
WHERE
bc.PostConfig & @PostConfig = @PostConfig
and bc.PostType | @PostType = @PostType
and bl.CategoryID = @CategoryID
and bc.DateAdded >= @StartDate and bc.DateAdded <= @StopDate
End
End
杀手3现形
3个表的INNER JOIN查询,这可是每次打开页面时有网站分类数*2次调用的呀,以数据库的压力可想而知了,当文章数量越来越多的时候,你会发现每次打开首页数据库服务器的CPU曲线都有个飙升。
----------------------------------------------------
处理掉这个问题,打开首页时数据库服务器平静多了~~~
后话:
cnblogs并无这个现象,说明DUDU很早就已经发现这个问题。
希望此文能给使用cnblog代码的同志一点帮助。