如果你在使用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 代码。
protected
void
Page_Load(
object
sender, System.EventArgs e)
{
CategoryLevel1.DataSource=Config.GetSiteBlogConfigCollection();
CategoryLevel1.DataBind();
}
在页面加载时调用了Config.GetSiteBlogConfigCollection()获取网站分类:
public
static
SiteBlogConfigCollection GetSiteBlogConfigCollection()
{
string
dataFile
=
System.Web.HttpContext.Current.Server.MapPath(
"
~/SiteBlogConfig.config
"
);
return
(SiteBlogConfigCollection)Util.SerializationHelper.Load(
typeof
(SiteBlogConfigCollection),dataFile);
}
杀手1现形:
这里在每次首页加载的时候都要加载.config,然后返回反序列化得到的对象。众所周知序列化和反序列化性能是很低的,而这里每次页面加载都重复做一次,对性能的影响就不可不计了。
接下来看刚才提到的CheckTitle()方法:
protected
string
CheckTitle(
string
title,
string
CategoryID)
{
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()方法,这个方法代码如下:
private
int
GetRowsCount(
bool
IsToday,BlogConfig config)
{
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中:
public
static
int
GetEntryCount(EntryQuery query)
{
return
DTOProvider.Instance().GetEntryCount(query);
}
我是使用sql数据库,所以这里跟踪转到Frameword/data/SqlDataProvider.cs:
public
IDataReader GetEntryCount(EntryQuery query)
{
return
GetReader(
"
blog_GenericGetEntriesCount_10
"
,EntryQueryParameters(query));
}
blog_GenericGetEntriesCount_10这个储存过程比较长,我们只来看和这次调用相关的代码:
--
Do we have a CategoryID?
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代码的同志一点帮助。
出处:http://wuchang.cnblos.com