Perf: lazy-loading more information which is used infrequently

site id is cached for SiteService.GetSiteSettings performance
HasComments part loads collections on demand
HasTags part loads collections on demand

--HG--
branch : dev
This commit is contained in:
Louis DeJardin
2010-05-16 19:47:51 -07:00
parent 98c1d931e0
commit 48be8159b9
5 changed files with 72 additions and 50 deletions

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Orchard.Caching;
using Orchard.Core.Settings.Models; using Orchard.Core.Settings.Models;
using Orchard.Data; using Orchard.Data;
using Orchard.Logging; using Orchard.Logging;
@@ -10,30 +11,38 @@ using Orchard.Settings;
namespace Orchard.Core.Settings.Services { namespace Orchard.Core.Settings.Services {
[UsedImplicitly] [UsedImplicitly]
public class SiteService : ISiteService { public class SiteService : ISiteService {
private readonly IRepository<SiteSettingsRecord> _siteSettingsRepository;
private readonly IContentManager _contentManager; private readonly IContentManager _contentManager;
private readonly ICacheManager _cacheManager;
public SiteService(IRepository<SiteSettingsRecord> siteSettingsRepository, IContentManager contentManager) { public SiteService(
_siteSettingsRepository = siteSettingsRepository; IRepository<SiteSettingsRecord> siteSettingsRepository,
IContentManager contentManager,
ICacheManager cacheManager) {
_contentManager = contentManager; _contentManager = contentManager;
_cacheManager = cacheManager;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
} }
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
public ISite GetSiteSettings() { public ISite GetSiteSettings() {
SiteSettingsRecord record = _siteSettingsRepository.Table.FirstOrDefault(); var siteId = _cacheManager.Get("SiteId", ctx => {
if (record == null) { var site = _contentManager.Query("site")
ISite site = _contentManager.Create<SiteSettings>("site", item => { .Slice(0, 1)
item.Record.SiteSalt = Guid.NewGuid().ToString("N"); .FirstOrDefault();
item.Record.SiteName = "My Orchard Project Application";
item.Record.PageTitleSeparator = " - "; if (site == null) {
}); site = _contentManager.Create<SiteSettings>("site", item => {
// ensure subsequent calls will locate this object item.Record.SiteSalt = Guid.NewGuid().ToString("N");
_contentManager.Flush(); item.Record.SiteName = "My Orchard Project Application";
return site; item.Record.PageTitleSeparator = " - ";
} }).ContentItem;
return _contentManager.Get<ISite>(record.Id); }
return site.Id;
});
return _contentManager.Get<ISite>(siteId);
} }
} }
} }

View File

@@ -20,23 +20,21 @@ namespace Orchard.Comments.Handlers {
Filters.Add(StorageFilter.For(hasCommentsRepository)); Filters.Add(StorageFilter.For(hasCommentsRepository));
OnActivated<HasComments>((ctx, x) => { OnActivated<HasComments>((ctx, x) => {
x.CommentsActive = true; x.CommentsActive = true;
x.CommentsShown = true; x.CommentsShown = true;
}); });
OnLoading<HasComments>((context, comments) => { OnLoading<HasComments>((context, comments) => {
//TODO: lazy loading? comments._comments.Loader(list => contentManager
comments.Comments = contentManager .Query<Comment, CommentRecord>()
.Query<Comment, CommentRecord>() .Where(x => x.CommentedOn == context.ContentItem.Id && x.Status == CommentStatus.Approved)
.Where(x => x.CommentedOn == context.ContentItem.Id && x.Status == CommentStatus.Approved) .List().ToList());
.List().ToList();
//TODO: lazy loading? comments._pendingComments.Loader(list => contentManager
comments.PendingComments = contentManager .Query<Comment, CommentRecord>()
.Query<Comment, CommentRecord>() .Where(x => x.CommentedOn == context.ContentItem.Id && x.Status == CommentStatus.Pending)
.Where(x => x.CommentedOn == context.ContentItem.Id && x.Status == CommentStatus.Pending) .List().ToList());
.List().ToList(); });
});
OnRemoved<HasComments>( OnRemoved<HasComments>(
(context, c) => { (context, c) => {

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.Utilities;
namespace Orchard.Comments.Models { namespace Orchard.Comments.Models {
public class HasComments : ContentPart<HasCommentsRecord> { public class HasComments : ContentPart<HasCommentsRecord> {
@@ -8,8 +9,11 @@ namespace Orchard.Comments.Models {
PendingComments = new List<Comment>(); PendingComments = new List<Comment>();
} }
public IList<Comment> Comments { get; set; } public readonly LazyField<IList<Comment>> _comments = new LazyField<IList<Comment>>();
public IList<Comment> PendingComments { get; set; } public readonly LazyField<IList<Comment>> _pendingComments = new LazyField<IList<Comment>>();
public IList<Comment> Comments { get { return _comments.Value; } set { _comments.Value = value; } }
public IList<Comment> PendingComments { get { return _pendingComments.Value; } set { _pendingComments.Value = value; } }
public bool CommentsShown { public bool CommentsShown {
get { return Record.CommentsShown; } get { return Record.CommentsShown; }

View File

@@ -14,26 +14,33 @@ namespace Orchard.Tags.Handlers {
Filters.Add(new ActivatingFilter<HasTags>("blogpost")); Filters.Add(new ActivatingFilter<HasTags>("blogpost"));
Filters.Add(new ActivatingFilter<HasTags>("page")); Filters.Add(new ActivatingFilter<HasTags>("page"));
OnLoading<HasTags>((context, ht) => { OnLoading<HasTags>((context, tags) => {
HasTags tags = context.ContentItem.As<HasTags>();
tags.AllTags = tagsRepository.Table.ToList(); // provide names of all tags on demand
IEnumerable<TagsContentItems> tagsContentItems = tagsContentItemsRepository.Fetch(x => x.ContentItemId == context.ContentItem.Id); tags._allTags.Loader(list => tagsRepository.Table.ToList());
foreach (var tagContentItem in tagsContentItems) {
Tag tag = tagsRepository.Get(tagContentItem.TagId); // populate list of attached tags on demand
tags.CurrentTags.Add(tag); tags._currentTags.Loader(list => {
} var tagsContentItems = tagsContentItemsRepository.Fetch(x => x.ContentItemId == context.ContentItem.Id);
}); foreach (var tagContentItem in tagsContentItems) {
var tag = tagsRepository.Get(tagContentItem.TagId);
list.Add(tag);
}
return list;
});
});
OnRemoved<HasTags>((context, ht) => { OnRemoved<HasTags>((context, ht) => {
tagsContentItemsRepository.Flush(); tagsContentItemsRepository.Flush();
HasTags tags = context.ContentItem.As<HasTags>(); HasTags tags = context.ContentItem.As<HasTags>();
foreach (var tag in tags.CurrentTags) { foreach (var tag in tags.CurrentTags) {
if (!tagsContentItemsRepository.Fetch(x => x.ContentItemId == context.ContentItem.Id).Any()) { if (!tagsContentItemsRepository.Fetch(x => x.ContentItemId == context.ContentItem.Id).Any()) {
tagsRepository.Delete(tag); tagsRepository.Delete(tag);
} }
} }
}); });
} }
} }
} }

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.Utilities;
namespace Orchard.Tags.Models { namespace Orchard.Tags.Models {
public class HasTags : ContentPart { public class HasTags : ContentPart {
@@ -8,7 +9,10 @@ namespace Orchard.Tags.Models {
CurrentTags = new List<Tag>(); CurrentTags = new List<Tag>();
} }
public IList<Tag> AllTags { get; set; } public readonly LazyField<IList<Tag>> _allTags = new LazyField<IList<Tag>>();
public IList<Tag> CurrentTags { get; set; } public readonly LazyField<IList<Tag>> _currentTags = new LazyField<IList<Tag>>();
public IList<Tag> AllTags { get { return _allTags.Value; } set { _allTags.Value = value; } }
public IList<Tag> CurrentTags { get { return _currentTags.Value; } set { _currentTags.Value = value; } }
} }
} }