更新:Se 底部:添加了 CreateArticleRelations 代码示例。
好的,这是一个棘手的问题。在预览和生产环境中,我在 hyper-v 中遇到了巨大的性能问题。
首先,这里是设置。
所有服务器上的 .NET 4.0。
预习
网络服务器:虚拟机,8gb 内存,4 cpu,windows server 2008 r2 (64)
数据库:虚拟服务器、6gb 内存、2 个 cpu、windows server 2008 r2 (64)
生产:
网络服务器:虚拟机,8gb 内存,4 个 cpu,windows server 2008 r2 (64)
数据库:物理机,48 gb 内存,16 cpu,windows server 2008 r2 (64)
这是一个在这些上运行的 B2B 商店。当为一种产品运行集成时,结果让我大吃一惊。我会提供图片。
在预览中运行一个产品需要:83 秒才能更新所有内容。在生产中运行一种产品需要 301 秒 (!) 才能更新所有内容。同款产品!
如果我在本地运行它,大约需要 40 秒才能完成。
我已经在两台服务器上运行了 dotTrace 远程分析,以实际查看需要时间的内容。我使用 EnterpriseLibrary 进行日志记录,使用 umbraco 进行 cms 和 uCommerce 作为商务平台。请看下面我看到的一个发现的图片示例。
首先,CreateArticleRelations 在生产服务器上需要 140 秒,但在预览版上只需要 46 秒。相同的产品,相同的数据。然后是真正时髦的东西。在顶部的生产站点上,我们看到企业日志记录需要 64 秒,但在预览运行时,它的速度已经下降,因此甚至不能说它完全没有时间。
日志记录的实现如下所示。
private string LogMessage(string message, int priority, string category, TraceEventType severity, int code, int skipFrames = 2)
{
//Check if "code" exists in eCommerceB2B.LogExceptions
var dbf = new ThirdPartSources();
var exeptions = dbf.GetLogExeptions();
foreach (var exeption in exeptions)
{
if (code.ToString() == exeption)
return DateTime.Now.ToString();
}
try
{
var stack = new StackTrace(skipFrames);
if (_logWriter.IsLoggingEnabled())
{
var logEntry = new LogEntry
{
Title =
stack.GetFrame(0).GetMethod().ReflectedType.FullName + " " +
stack.GetFrame(0).GetMethod(),
Message = message,
Priority = priority,
Severity = severity,
TimeStamp = DateTime.Now,
EventId = code
};
logEntry.Categories.Add(category);
_logWriter.Write(logEntry);
return logEntry.TimeStampString;
}
日志记录设置为滚动平面文件和数据库。我试图禁用日志记录并节省了大约 20 秒,但 LogMessage 仍然位于顶部。
这几天让我大吃一惊,我似乎无法找到解决方案。当然我可以完全删除日志记录,但我不想找到问题的原因。
令我困扰的是,例如在生产服务器上运行一种方法 (CreateArticleRelations) 所需的时间几乎是其 4 倍。cpu 级别永远不会超过 30 %,并且 5 gb 内存可用。这些应用程序作为控制台应用程序运行。
有人请救救我!:) 如果需要,我可以提供更多数据。我敢打赌,这与虚拟服务器有关,但我不知道要检查什么。
更新:
根据评论,我尝试完整地注释掉 LogMessage。它总共节省了大约 100 秒,这告诉我有些事情是非常错误的。仍然需要 169 秒来创建关系,而在预览中需要 46 秒,并且在预览中日志记录仍处于启用状态。企业库使其以这种方式运行可能有什么问题?而且,为什么我的代码在生产服务器上运行速度要慢 4 倍?删除 LogMessage 后的图像。它来自生产。
创建文章关系
private void CreateArticleRelations(Product uCommerceProduct, IStatelessSession session)
{
var catalogues = _jsbArticleRepository.GetCustomerSpecificCatalogue(uCommerceProduct.Sku).CustomerRelations;
var defaultCampaignName = _configurationManager.GetValue(ConfigurationKeys.UCommerceDefaultCampaignName);
var optionalArticleCampaignName = _configurationManager.GetValue(ConfigurationKeys.UCommerceDefaultOptionalArticleCampaignName);
var categoryRelations =
session.Query<CategoryProductRelation>()
.Fetch(x => x.Category)
.Fetch(x => x.Product)
.Where(
x =>
x.Category.Definition.Name == _customerArticleCategory && x.Product.Sku == uCommerceProduct.Sku)
.ToList();
var relationsAlreadyAdded = _categoryRepository.RemoveCataloguesNotInRelation(catalogues, categoryRelations,
session);
_categoryRepository.SetArticleCategories(session, relationsAlreadyAdded, uCommerceProduct, catalogues,
_customerCategories, _customerArticleCategory,
_customerArticleDefinition);
//set campaigns and optional article
foreach (var jsbArticleCustomerRelation in catalogues)
{
// Article is in campaign for just this user
if (jsbArticleCustomerRelation.HasCampaign)
{
_campaignRepository.CreateCampaignAndAddProduct(session, jsbArticleCustomerRelation, defaultCampaignName);
}
else // remove the article from campaign for user if exists
{
_campaignRepository.DeleteProductFromCampaign(session, jsbArticleCustomerRelation, defaultCampaignName);
}
// optional article
if(jsbArticleCustomerRelation.IsOptionalArticle)
{
_campaignRepository.CreateCampaignAndAddProduct(session, jsbArticleCustomerRelation, optionalArticleCampaignName);
}
else
{
_campaignRepository.DeleteProductFromCampaign(session, jsbArticleCustomerRelation, optionalArticleCampaignName);
}
}
}
我们以某种方式几乎在每一行上都访问了数据库。例如,在 DeleteProductFromCampaign 中,以下代码在预览环境中需要 43 秒,在生产环境中需要 169 秒。
public void DeleteProductFromCampaign(IStatelessSession session, JSBArticleCustomerRelation jsbArticleCustomerRelation, string campaignName)
{
var productTarget =
session.Query<ProductTarget>()
.FirstOrDefault(
x =>
x.CampaignItem.Campaign.Name == jsbArticleCustomerRelation.CustomerNumber &&
x.CampaignItem.Name == campaignName &&
x.Sku == jsbArticleCustomerRelation.ArticleNumber);
if (productTarget != null)
{
session.Delete(productTarget);
}
}
因此,例如,此代码在生产服务器上的运行速度要慢 4 倍。服务器之间最大的区别是生产(物理)服务器设置了许多实例,而我正在使用其中一个(20 gb om ram)。