04 Jul 2007

讨论一下类似BlogEngine为何要一次性加载所有Post到内存

Share

试验了一下给BlogEngine生成10000个post 程序第一次运行时等待的时间让我想自杀(白屏了近2分钟)
看了一下代码,发现BlogEngine在第一次运行时候加载所有Post(从数据库)到List内,类似(Early initialization)
当新添加post时,给数据库(xml/database)内加入该post同时给List内追加该post
删除一个post时候从数据库(xml/database)内删除并从List内remove该post

  1
  2private string _Content;
  3/// <summary>
  4/// Gets or sets the Content or the post.
  5/// </summary>

  6public string Content
  7{
  8  get
  9  {
 10      if ( _Content == null )
 11      {
 12        _Content = LoadPostContent( this.Id );
 13      }

 14      return _Content;
 15  }

 16  set
 17  {
 18      if ( _Content != value )
 19      MarkDirty( "Content" );
 20      _Content = value;
 21  }

 22}

 23private string LoadPostContent(Guid id)
 24{    
 25    string content = null;
 26    
 27    string key = string.Format("Be:Content:{0}",id);
 28    
 29    // if there is no content cached
 30    object obj = HttpContext.Current.Cache.Get(key);
 31    if(obj == null)
 32    {
 33        // load the post's content from provider here
 34        content =  BlogService.LoadPostContent( id );
 35        
 36        HttpContext.Current.Cache.Insert(key, content, null, DateTime.Now.AddMinutes(2), TimeSpan.Zero);
 37            
 38        // if use xml store the data 
 39        // 更丑陋点的 new CacheDependency(_Folder + "posts\\" + id.ToString() + ".xml") in the Cache.Insert Method 
 40    }

 41
 42}

 43
 44private static object _SyncRoot = new object();
 45private static List<Post> _Posts;
 46/// <summary>
 47/// A sorted collection of all posts in the blog.
 48/// Sorted by date.
 49/// </summary>

 50public static List<Post> Posts
 51{
 52    get
 53    {
 54        lock (_SyncRoot)
 55        {
 56          if (_Posts == null)
 57          {
 58            //in provider the 'FillPosts' method' dose not return the 'real'  content' per post; 
 59
 60            _Posts = BlogService.FillPosts( );
 61          }

 62          return _Posts;
 63        }

 64    }

 65}

 66
 67in XmlBlogProvider
 68
 69/// <summary>
 70/// Retrieves a post based on the specified Id.
 71/// </summary>

 72public override Post SelectPost(Guid id)
 73{
 74    string fileName = _Folder + "posts\\" + id.ToString() + ".xml";
 75    Post post = new Post();
 76    XmlDocument doc = new XmlDocument();
 77    doc.Load(fileName);
 78
 79    post.Title = doc.SelectSingleNode("post/title").InnerText;
 80    post.Description = doc.SelectSingleNode("post/description").InnerText;
 81
 82    post.Content = null;  // dose not return the 'real'  content'
 83
 84    post.DateCreated = DateTime.Parse(doc.SelectSingleNode("post/pubDate").InnerText);
 85    post.DateModified = DateTime.Parse(doc.SelectSingleNode("post/lastModified").InnerText);
 86    
 87    // setting other filed
 88
 89    return post;
 90}

 91Post class in Business object layer
 92
 93private string _Content;
 94/// <summary>
 95/// Gets or sets the Content or the post.
 96/// </summary>

 97public string Content
 98{
 99  get
100  {
101      if ( _Content == null )
102      {
103      _Content = LoadPostContent( this.Id );
104      }

105      return _Content;
106  }

107  set
108  {
109      if ( _Content != value )
110      MarkDirty( "Content" );
111      _Content = value;
112  }

113}

114private string LoadPostContent(Guid id)
115{    
116    string key = string.Format("Be:Content:{0}",id);
117    string content = null;
118    // if there is no content cached by id
119    object obj = HttpContext.Current.Cache.Get(key);
120    if(obj == null)
121    {
122        // load the post's content from provider here
123        content =  BlogService.LoadPostContent( id );
124        
125        HttpContext.Current.Cache.Insert(key, content, null, DateTime.Now.AddMinutes(2), TimeSpan.Zero);
126            
127        // if use xml store the data 
128        // we can use a  CacheDependency like new CacheDependency(_Folder + "posts\\" + id.ToString() + ".xml") in the Cache.Insert Method 
129    
130    return content;
131    }

132    return (strong)obj;
133
134}

135
136private static object _SyncRoot = new object();
137private static List<Post> _Posts;
138/// <summary>
139/// A sorted collection of all posts in the blog.
140/// Sorted by date.
141/// </summary>

142public static List<Post> Posts
143{
144    get
145    {
146        lock (_SyncRoot)
147        {
148          if (_Posts == null)
149          {
150            //in provider the 'FillPosts' method' dose not return the 'real'  content' per post; 
151
152            _Posts = BlogService.FillPosts( );
153          }

154          return _Posts;
155        }

156    }

157}

158
159in XmlBlogProvider
160
161/// <summary>
162/// Retrieves a post based on the specified Id.
163/// </summary>

164public override Post SelectPost(Guid id)
165{
166    string fileName = _Folder + "posts\\" + id.ToString() + ".xml";
167    Post post = new Post();
168    XmlDocument doc = new XmlDocument();
169    doc.Load(fileName);
170
171    post.Title = doc.SelectSingleNode("post/title").InnerText;
172    post.Description = doc.SelectSingleNode("post/description").InnerText;
173
174    post.Content = null// dose not return the 'real'  content'
175
176    post.DateCreated = DateTime.Parse(doc.SelectSingleNode("post/pubDate").InnerText);
177    post.DateModified = DateTime.Parse(doc.SelectSingleNode("post/lastModified").InnerText);
178    
179    // setting other fileds
180
181    return post;
182}

个人觉得 是否应该对于Content、Comment这种占用大量内存的字段是否该采用类似Lazy Initialization 的方式
说明:第一次加载所有post时候 post list内的item不带真实的comtent和comment等
然后在用到的时候再从数据库读取,然后放入缓存,下次备用
这样Posts内的item都变的瘦多了,类似于延迟初始化(Lazy Initialization )
请大家讨论讨论,谢谢!

comments powered by Disqus