我正在处理一些更新UCommerce中的项目的代码(不是我自己的代码)。这个特定的代码块更新了产品的UDF。我遇到了执行速度的问题。通过foreach
循环的每次迭代都比前一次慢。执行开始时,它每秒循环5-6次,但是当它处理500次迭代时,它每5-6秒减速到1次,现在是910项,每10-11秒减速到1次。正如代码所示,它在提交事务和刷新会话之前处理200(_batchsize
)项。
内存,CPU和磁盘IO看起来都很好。没有过多的CPU使用率,充足的可用内存和没有磁盘瓶颈。运行应用程序时,内存使用率保持稳定在350Mb左右。
无论是从IDE还是已编译的exe运行它,我都会看到同样的问题。
我已经尝试减少批量大小,我也尝试提交事务并刷新每个项目的会话但它没有什么区别。我只是想知道是否有人可以提出任何我可以尝试的建议,甚至可以确定可能的问题区域。
public class ccProductUDFs
{
public string ProductName { get; set; }
public string FieldName { get; set; }
public string DataType { get; set; }
public string DisplayName { get; set; }
public string SKU { get; set; }
public bool Facet { get; set; }
public bool Searchable { get; set; }
public bool RenderInEditor { get; set; }
public string DefinitionName { get; set; }
public string DefinitionDescription { get; set; }
public string UdfValue { get; set; }
public bool UdfValueHasChanged { get; set; }
public bool UdfFieldHasChanged { get; set; }
public bool UdfFieldDeleted { get; set; }
public bool DisplayOnSite { get; set; }
public string CultureCode { get; set; }
public override string ToString()
{
return string.Format("{0} {1} : {2} = {3}", this.SKU, this.ProductName, this.DisplayName, this.UdfValue);
}
}
//This will load approx. 173000 item for a SQL database
List<ccProductUDFs> listudfs = ccProductUDFsData.Load(DBConfiguration.GetDBContext());
//_batchsize is set to 200
//processUdFs is a Boolean = true stored in AppSettings
#region Update any UDFs...
_startrange = 0;
started = DateTime.Now;
timeTaken = TimeSpan.MinValue;
timeLeft = TimeSpan.MinValue;
doneCount = 0;
_totalCount = listudfs.Count();
while (_processUdFs && _startrange < listudfs.Count())
{
int sz = listudfs.Count() - _startrange >= _batchsize ? _batchsize : listudfs.Count() - _startrange;
List<ccProductUDFs> shallowlist = listudfs.GetRange(_startrange, sz);
_startrange = _startrange + sz;
_session = SessionContext.Session;
// create a response list to hold results of uploads...
List<ccResponse> response_categoryUDFs = new List<ccResponse>();
// start the transaction
using (var tx = _session.BeginTransaction())
{
_dbcontext.BeginTransaction();
int counter = 0;
int listcount = listudfs.Count();
// loop through each remaining UDF
// these are UDFs where the FIELD or the VALUE has changed, and we have not dealt with it as part of the product
foreach (ccProductUDFs udf in shallowlist)
{
if (ShowLog(verbose, (_startrange - sz) + ++counter, listcount))
{
TimeSpan elapsed = (DateTime.Now - started);
WriteLogV2("product udfs {0} of {1}", (_startrange - sz) + counter, listcount, elapsed);
}
// get the product for this UDF...
var product = _session.Query<Product>().FirstOrDefault(a => a.Sku == udf.SKU);
if (product != null)
{
// check that product has a product definition...
if (product.ProductDefinition == null)
{
// product has no definition assigned, so check that the product definition exists in data...
ProductDefinition definition = _session.Query<ProductDefinition>().FirstOrDefault(a => a.Description == udf.DefinitionName);
if (definition == null)
{
// product definition doesn;t exist in data, so create it...
definition = new ProductDefinition();
definition.Description = udf.DefinitionDescription;
definition.Name = udf.DefinitionName;
// save the changes...
_session.SaveOrUpdate((ProductDefinition)definition);
}
// assign this product definition to the product record...
product.ProductDefinition = definition;
}
// determine if the UDF FIELD exists...
ProductDefinitionField definitionfield = product.ProductDefinition.ProductDefinitionFields.FirstOrDefault(a => a.Name == udf.FieldName);
if (definitionfield == null)
{
// the UDF FIELD does NOT exist, so we shall add it.
definitionfield = new ProductDefinitionField();
definitionfield.Name = udf.FieldName;
definitionfield.ProductDefinition = product.ProductDefinition;
// locate the data type record and assign it to this UDF FIELD
var dt = _session.Query<DataType>().FirstOrDefault(a => a.TypeName == udf.DataType);
if (dt != null)
{
definitionfield.DataType = dt;
}
// add the UDF FIELD to the product category...
product.ProductDefinition.ProductDefinitionFields.Add(definitionfield);
// save the changes...
_session.SaveOrUpdate((Product)product);
}
bool changed = definitionfield.Deleted != udf.UdfFieldDeleted;
// assign properties to this UDF FIELD...
definitionfield.Deleted = udf.UdfFieldDeleted;
if (changed)
{
// save the changes...
_session.SaveOrUpdate((ProductDefinitionField)definitionfield);
}
// determine if the UDF VALUE record exists...
ProductProperty property = product.ProductProperties.FirstOrDefault(a => a.ProductDefinitionField.Name == definitionfield.Name && a.Product.Id == product.ProductId);
if (property == null)
{
// the UDF VALUE does NOT exist, so we shall add it.
property = new ProductProperty();
property.ProductDefinitionField = definitionfield;
property.Product = product;
// add the UDF VALUE to the product category...
product.ProductProperties.Add(property);
}
changed = false;
string v = udf.UdfValue == null ? string.Empty : udf.UdfValue.Trim();
changed = property.Value != v;
// assign properties to this UDF FIELD...
property.Value = v;
if (changed)
{
// save the changes...
_session.SaveOrUpdate((ProductProperty)property);
// save the changes...
_session.SaveOrUpdate((Product)product);
}
// update the response with a successful result...
response_categoryUDFs.Add(new ccResponse(udf.SKU, udf.FieldName, ccCategoryUDFsData.Source, true, "", 0));
}
object[] prodparam =
{
_dbcontext.NewParameter("@Sku", udf.SKU),
_dbcontext.NewParameter("@udfName", udf.FieldName)
};
_dbcontext.ExecuteNonQuery(CommandType.Text,
"UPDATE [LOAD_ProductUdfValues] SET HasChanged = 0 WHERE ProductId = @Sku And FieldName = @udfName",
prodparam);
TimeSpan ts = DateTime.Now - started;
doneCount++;
Console.WriteLine("Done {0} of {1} in {2}", doneCount, _totalCount, ts.ToString(@"hh\:mm\:ss"));
}
try
{
// commit all changes...
tx.Commit();
_dbcontext.CommitTransaction();
}
catch (Exception ex)
{
// Error Handler
tx.Rollback();
_dbcontext.RollbackTransaction();
response_categoryUDFs.Clear();
response_categoryUDFs.Add(new ccResponse("", "", ccCatalogData.Source, false, "Commit failed [" + ex.ToString() + "]", 1));
}
}
// send any response...
ccResponse.Write(_dbcontext, response_categoryUDFs, ccCatalogData.ResponseTarget);
// tidy up the session before is it disposed...
_session.Flush();
// }
}
#endregion
答案 0 :(得分:0)
如果有人在搜索中发现这一点,我已在_session.Clear();
_session.Flush();
修复了我的问题