nopCommerce 1.7 cache not working?! Possible solution to 1.7 slowness?

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
13 years ago
thought wrote:
Fuzion

Images are cached in the file system even if using the DB.


WHat do you mean? Do you store them in your database?
If you store the pics in db than you carry arround all the bytes in memory, which would come from the db.
Anyways, I'm not saying this is your problem however.
13 years ago
Deval,

Putting the entire collection into the cache is one approach (it's exactly what i've done with settings in my tests) but I think its going to vary depending on the entity - of course very easy to tweak what you cache.

Fuzion,

Definitely not ruling out CDN cache. This is the benefit of using an interface for our caching provider since you can swap that out for CDN, Memory Cache, File System Cache, Http Context or whatever you want.
13 years ago
This the CacheProvider I implemented:


namespace NopSolutions.NopCommerce.BusinessLogic.Caching {
    public interface ICacheProvider {
        T Get<T>(string key);
        void Set(string key, object data, int cacheTime);
        bool IsSet(string key);
        void Invalidate(string key);
    }
}

namespace NopSolutions.NopCommerce.BusinessLogic.Caching {
    public class MemoryCacheProvider : ICacheProvider {
        
        ObjectCache Cache { get { return MemoryCache.Default; } }

        public T Get<T>(string key) {
            return (T)Cache[key];
        }

        public void Set(string key, object data, int cacheTime) {
            var policy = new CacheItemPolicy();
            policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
            Cache.Add(new CacheItem(key, data), policy);
        }

        public bool IsSet(string key) {
            return (Cache.Contains(key));
        }

        public void Invalidate(string key) {
            Cache.Remove(key);
        }
    }
}




You will need to add a reference to System.Runtime.Caching.

A sample usage:


        private static ICacheProvider Cache { get { return new MemoryCacheProvider(); } }

        /// <summary>
        /// Gets all categories filtered by parent category identifier
        /// </summary>
        /// <param name="parentCategoryId">Parent category identifier</param>
        /// <param name="showHidden">A value indicating whether to show hidden records</param>
        /// <returns>Category collection</returns>
        public static List<Category> GetAllCategoriesByParentCategoryId(int parentCategoryId,
            bool showHidden)
        {
            string key = string.Format("nop.category.parent-{0}-{1}", parentCategoryId.ToString(), showHidden.ToString());

            if (Cache.IsSet(key))
                return Cache.Get<List<Category>>(key);

            var context = ObjectContextHelper.CurrentObjectContext;
            var query = from c in context.Categories
                        orderby c.DisplayOrder
                        where (showHidden || c.Published) &&
                        !c.Deleted &&
                        c.ParentCategoryId == parentCategoryId
                        select c;
            var categories = query.ToList();

            Cache.Set(key, categories, 30);

            return categories;
        }


This particular query isn't exactly slow to execute ( < 1ms) but it soon pays for itself.

On default.aspx this query is executed once (root categories)
On a root category page is it executed 3 times
On a sub category page it is executed 4 times
and so on

So even for a simple method like this, performance improvements can be made.

Of course the real benefit is going to be sorting the GetAllProducts method. Rather than pulling all products into cache (as someone suggested) I would prefer to see this refactored into simplified methods and us caching each collection individually. This allows your cache invalidation to be much more targeted.
13 years ago
nopCommerce team | retroviz wrote:
snip


nice work! Now please get Andrei to put this in to 1.9 :)
13 years ago
nopCommerce team | retroviz wrote:
This the CacheProvider I implemented:



        private static ICacheProvider Cache { get { return new MemoryCacheProvider(); } }

            string key = string.Format("nop.category.parent-{0}-{1}", parentCategoryId.ToString(), showHidden.ToString());

            if (Cache.IsSet(key))
                return Cache.Get<List<Category>>(key);



So if you have 100+ Categories with parents and subordinates, you'll end up with with duplicates in your cache (when every category was requested). Sounds like waste of memory for me.

The only thing that speaks against fetching all categories into cache is if the server is low on memory and you have lots of data. But then, if you want a professional product you need some dedicated server or vps

But I would be happy if at least this is implemented in Nop 1.9.

Deval
13 years ago
deval wrote:


So if you have 100+ Categories with parents and subordinates, you'll end up with with duplicates in your cache (when every category was requested). Sounds like waste of memory for me.

The only thing that speaks against fetching all categories into cache is if the server is low on memory and you have lots of data. But then, if you want a professional product you need some dedicated server or vps

But I would be happy if at least this is implemented in Nop 1.9.

Deval


I don't understand how there would be duplicates?

IIS will purge cache if memory is running low. Remember though its only text being stored in memory which is relatively small.
13 years ago
ok, let me correct my statement.

in the scenario stated there are no duplicates.
I was thinking about fetching all categories related to a parent cateory
like

Cat 1
  -- Cat 2
     -- Cat 3

So Cat 1 is main with one child which has another child.
So if you say get me all children from 1 you would get 2 and 3.
If you said give me all where parent is 2 you get 3
So you would have cat 3 twice in cache.
BUT, the method mentioned doesn't do that, thats how i implemented mine. So, sorry for the confusion. Next time I'll read more carefully.

Deval
13 years ago
Deval,

It's okay, I understand what you are saying.

The object collection that is cached will always be unique ("all categories in parent 10" is technically different from "all categories in parent 5"), but it is true that the same category may exist in both collections.

This article has a good solution and means you are only caching the object once.
13 years ago
I'm working on more configurable caching in upcoming nopCommerce 1.90. If I start using static caching (like it was used in nopCommerce 1.60), then we get the error related to navigation properties and using distinct ObjectContexts:

To reproduce follow the next steps:
1. Load a shipping method (go to a shipping method details page). So now we have it cached.
2. Then go to shipping methods page (Admin Area > Configuration > Shipping > Shipping Methods) and try to modify several country restrictions.
3. You'll get the following error 'An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key' because the shipping method that you try to restrict is already cached, but it belongs to another object context (object context created in one of previous request - step 1).

I really don't know how to resolve this issue. Any advice would be appreciated
13 years ago
nopCommerce team | a.m. wrote:
snip


Does this answer your question?

http://stackoverflow.com/questions/1131779/unable-to-attach-a-detached-entity-an-object-with-the-same-key-already-exists-i


http://www.kodyaz.com/forums/thread/12805.aspx
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.