Performance optimization needed - NOPCOMMERCE IS TOO SLOW !

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
9 years ago
Hi, use AsParallels is generated problems?, I my tests there was some gain in performance

public virtual T GetById(object id)
{        
        Entities.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism);
        return this.Entities.Find(id);
  }
9 years ago
Hi Andrei,
You have added SupportPreviousNopcommerceVersions parameter to improve performance, it's a good idea!

Imagine now I have migrated 6 month ago, google and other search engine have correctly changed all urls because of 301 redirections, and they is only a few old urls leaving on the web, in some forums, blogs etc.
I would expect to change SupportPreviousNopcommerceVersions to false and manually set the last redirections using UrlRecord table.

But it's not possible, because if I set a slug with slashes, it won't work :(

Do you think you could allow slashes in slugs for the next version?

Thanks for all you performance efforts

Nicolas
9 years ago
nicolas.muniere wrote:
Hi Andrei,
You have added SupportPreviousNopcommerceVersions parameter to improve performance, it's a good idea!

Imagine now I have migrated 6 month ago, google and other search engine have correctly changed all urls because of 301 redirections, and they is only a few old urls leaving on the web, in some forums, blogs etc.
I would expect to change SupportPreviousNopcommerceVersions to false and manually set the last redirections using UrlRecord table.

But it's not possible, because if I set a slug with slashes, it won't work :(

Do you think you could allow slashes in slugs for the next version?

Thanks for all you performance efforts

Nicolas

Not sure that I got you. Slashes never were supported in slugs and not sure that it'll possbile to support them easily. It's not somehow related to SupportPreviousNopcommerceVersions settings.
9 years ago
a.m. wrote:
Hi Andrei,


Nicolas
Not sure that I got you. Slashes never were supported in slugs and not sure that it'll possbile to support them easily. It's not somehow related to SupportPreviousNopcommerceVersions settings.



Perhaps I misunderstood this parameter.
My idea was if I someone is linking my web site on an old url like /category/5-apparel.aspx I'm not able to manually add this slug in UrlRecords because it's containing a /
It would be great to support this, and probably not difficult. UrlRecords is actually only used to support url changes, it could become easily a general redirection system.
9 years ago
the workaround for that is for GenericPathRoute to map to {*generic_name} rather than {generic_name} I believe.
9 years ago
sproaty wrote:
the workaround for that is for GenericPathRoute to map to {*generic_name} rather than {generic_name} I believe.


Absolutly, it's working! Do you think this workaround has some defects? I'm not at ease with routes. Can it slow down the solution, for example by catching all non needed requests?

Thanks for this solution,
Nicolas
9 years ago
nicolas.muniere wrote:
the workaround for that is for GenericPathRoute to map to {*generic_name} rather than {generic_name} I believe.

Absolutly, it's working! Do you think this workaround has some defects? I'm not at ease with routes. Can it slow down the solution, for example by catching all non needed requests?

Thanks for this solution,
Nicolas

Some time ago I created a work item. I've added one comment to its description. Please have a look (not sure about it)
9 years ago
a.m. wrote:

Some time ago I created a work item. I've added one comment to its description. Please have a look (not sure about it)


For now the only thing I notice is that each missing static ressource like /content/files/missingfile.pdf is catched by GenericPathRoute, it's not a big problem, but I'm not sure of the consequences.
9 years ago
Unfortunately that's true, which means it'll try and do a database lookup for that URL. However, nothing will be found and null is returned, so all is okay.
To avoid the database lookup, you could modify the Route to return null if the incoming URL (routeValues["se_name"]) contains a file extension before it uses the urlRecordService to lookup the URL.

And about performance - it should be fine because well...you want to try and match all incoming URLs! The route returns null if nothing is found in the DB, which is the indicator to MVC that this route did not match, and to go on to the next route in the RouteCollection and try and match that. If that doesn't match, try the next; etc, etc.

In one site I run I have two routes mapped to {*url} - one for custom CMS-driven pages, another for custom URL aliases admins can create (e.g. url "12345" is an alias of "some/other/page" - so when you visit www.website.com/12345, the MVC controller & action that maps to some/other/page is run. So, I need both routes to run and it works great
9 years ago
nicolas.muniere wrote:
...
ProductLoadAllPaged should be used only for search page.
...


I agree with Nicolas.  I just played with LinqPad rewriting some queries in just Linq and the generated SQL is good.
void Main()
{
  string connString = "Data Source=SERVER;Initial Catalog=nopCommerce_330_sample;Integrated Security=False;Persist Security Info=False;User ID=UID;Password=PWD;MultipleActiveResultSets=True";
  var dbContext = new Nop.Data.NopObjectContext(connString);
    
  var _productRepository = new Nop.Data.EfRepository<Product>(dbContext);  
  var products = _productRepository.Table;

  var _storeMappingRepository = new Nop.Data.EfRepository<StoreMapping>(dbContext);  
  var storeMappings = _storeMappingRepository.Table;  

  int storeId = 0;
  int categoryId = 2;
  
//  var query =
//    from p in products
//    where !p.Deleted
//      && p.Published
//      && p.VisibleIndividually
//    select p;

  var query = products.Where(p => !p.Deleted && p.Published && p.VisibleIndividually);
  
  query = query.Where(p => p.ProductCategories.Any(pc => pc.Id == categoryId));
  //query = query.Where(p => p.ProductCategories.Any(pc => new List<int>(){2,3,4}.Contains(pc.Id) )); //e.g. include sub categories
  //query = query.Where(p => p.ProductCategories.Any(pc => pc.Id == 2 && pc.IsFeaturedProduct));


  //store mapping
//  query = query.Where(p => !p.LimitedToStores
//               || (storeMappings.Any(sm => sm.EntityId == p.Id && sm.EntityName == "Product" && sm.StoreId == storeId))
//            );
  
  query.Take(15).Dump();

  //numberOfProducts
  var filteredProducts = products
    .Where(p => !p.Deleted && p.Published && p.VisibleIndividually)
    .Where(p => p.ProductCategories.Any(pc => pc.Id == categoryId));
    
  // this can be optionally included only if multi-store  (the nested ".Any()" becomes a "AND EXISTS (SELECT ..." )
  if (storeId > 0)
  {
    filteredProducts = filteredProducts
      .Where(p => !p.LimitedToStores
                         || (storeMappings.Any(sm => sm.EntityId == p.Id && sm.EntityName == "Product" && sm.StoreId == storeId)));
  }
    
  int numberOfProducts = filteredProducts.Count();
  numberOfProducts.Dump("numberOfProducts");
  //--------

}


Here are my notes / snippets from the nopC code; you can see that several calls to SearchProducts can be replaced by using bits from above.


//  FROM ProductLoadAllPaged sp
//          
//      AND (p.LimitedToStores = 0 OR EXISTS (
//        SELECT 1 FROM [StoreMapping] sm with (NOLOCK)
//        WHERE [sm].EntityId = p.Id AND [sm].EntityName = ''Product'' and [sm].StoreId=' + CAST(@StoreId AS nvarchar(max)) + '
//        ))'
//      
//          AND p.VisibleIndividually = 1
//          
//    LEFT JOIN Product_Category_Mapping pcm with (NOLOCK)
//      ON p.Id = pcm.ProductId    
//      
//        AND pcm.CategoryId
//
//      
//

//\Presentation\Nop.Web\Controllers\CatalogController.cs      
//        protected int GetCategoryProductNumber(int categoryId)      
//                var categoryIds = new List<int>();
//                categoryIds.Add(categoryId);
//                //include subcategories
//                if (_catalogSettings.ShowCategoryProductNumberIncludingSubcategories)
//                    categoryIds.AddRange(GetChildCategoryIds(categoryId));
//                var numberOfProducts = _productService
//                    .SearchProducts(categoryIds: categoryIds,
//                    storeId: _storeContext.CurrentStore.Id,
//                    visibleIndividuallyOnly: true,
//                    pageSize: 1)
//                    .TotalCount;
//                return numberOfProducts;      
//
//        public ActionResult Category(int categoryId, CatalogPagingFilteringModel command)
//                    featuredProducts = _productService.SearchProducts(
//                       categoryIds: new List<int>() { category.Id },
//                       storeId: _storeContext.CurrentStore.Id,
//                       visibleIndividuallyOnly: true,
//                       featuredProducts: true);      
//      
//        public ActionResult RecentlyAddedProducts()
//        public ActionResult RecentlyAddedProductsRss()    
//                var products = _productService.SearchProducts(
//                    storeId: _storeContext.CurrentStore.Id,
//                    visibleIndividuallyOnly: true,
//                    orderBy:ProductSortingEnum.CreatedOn,
//                    pageSize:_catalogSettings.RecentlyAddedProductsNumber);
//          
//          
//        public ActionResult ProductsByTag(int productTagId, CatalogPagingFilteringModel command)
//            var products = _productService.SearchProducts(
//                storeId: _storeContext.CurrentStore.Id,
//                productTagId: productTag.Id,
//                visibleIndividuallyOnly: true,
//                orderBy: (ProductSortingEnum)command.OrderBy,
//                pageIndex: command.PageNumber - 1,
//                pageSize: command.PageSize);
//
//\Presentation\Nop.Web\Controllers\CommonController.cs
//                var products = _productService.SearchProducts(storeId: _storeContext.CurrentStore.Id,
//                    visibleIndividuallyOnly: true,
//                    pageSize: 200);
//
//
//\Presentation\Nop.Web\Administration\Controllers\ProductController.cs
//        public ActionResult DownloadCatalogAsPdf()
//                var products = _productService.SearchProducts(vendorId: vendorId, showHidden: true);
//
//
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.