【发布时间】:2019-11-21 20:31:48
【问题描述】:
我正在使用 .Net Core 2.1 和 Visual Studio 2017。
问题
我正在与未实现 ISerializable 的第三方 dll class 对象合作。我正在尝试将这种类型的 4k+ 对象转换为另一种自定义类型,然后将它们序列化以从 API 传递回 Web 应用程序。将 1000 个对象转换为可序列化类型大约需要 55 秒,API 返回 JSON 的等待时间总计 2:30 分钟。
我的尝试
我尝试启动多个任务以将一批 1000 个 3rd 方对象转换为自定义可序列化类对象,然后将所有任务结果合并到一个列表中进行序列化。我尝试从使用列表切换到使用数组。我尝试使用Parallel.ForEach 和ConcurrentBag 进行转换。无论我尝试哪种方式,似乎都需要大约 50 - 60 秒才能将 1000 个这些对象转换为自定义可序列化类型。我怀疑其中大部分来自于在第 3 方列表的每次迭代中对new 的调用。我还尝试使用 String Builder 进行字符串连接,通过迭代第 3 方列表并通过连接将属性放入字符串中来创建 JSON 数据结果,这对.ToString()的调用似乎也很慢@
如果有人可以在这方面给我一些帮助,我真的很想提高性能时间。我读到使用struct 可能是一个更好的解决方案,但我还没有尝试过。我希望有一种方法可以快速做到这一点并且仍然使用classes。
代码示例
//OnBaseSearchDocument is my custom class which is serializable
OnBaseSearchDocument[] items = new OnBaseSearchDocument[sizeOfList];
//The class itself
public class OnBaseSearchDocument
{
public string Name { get; set; }
public long DocumentId { get; set; }
public string DocumentType { get; set; }
public string DocStorageDate { get; set; }
public string DocRevisionDate { get; set; }
public string DocumentDate { get; set; }
//Switched to using long for dates so I didn't call .ToString() on DateTimes of 3rd party class
//For the string props above
public long DocDate { get; set; }
public long DocReviseDate { get; set; }
public long DocStoreDate { get; set; }
}
//Trying to convert
//items is an array of custom class type I created that are serializable
//Hyland.Unity.Document is a 3rd party class contained in a dll - Not Serializable
foreach(Hyland.Unity.Document d in dl)
{
items[counter] = new OnBaseSearchDocument() { DocumentId = d.ID, Name = d.Name, DocumentType = d.DocumentType.Name, DocDate = d.DocumentDate.Ticks, DocReviseDate = d.LatestRevision.Date.Ticks, DocStoreDate = d.DateStored.Ticks };
counter++;
}
编辑
所以,我改用struct 而不是class:
[Serializable]
public struct StructOnBaseSearchDocument
{
public string Name { get; set; }
public long DocumentId { get; set; }
public string DocumentType { get; set; }
public string DocStorageDate { get; set; }
public string DocRevisionDate { get; set; }
public string DocumentDate { get; set; }
}
for (int i = 0; i < dl.Count; i++)
{
Structs.StructOnBaseSearchDocument st = new Structs.StructOnBaseSearchDocument()
{
DocumentId = dl[i].ID,
Name = dl[i].Name,
DocumentType = dl[i].DocumentType.Name,
DocStorageDate = dl[i].DateStored.ToString(),
DocRevisionDate = dl[i].LatestRevision.Date.ToString(),
DocumentDate = dl[i].DocumentDate.ToString()
};
foundDocs[counter] = st;
counter++;
}
我使用秒表来计时 - 在上述循环中将 1000 个 Hyland.Unity.Document 类型的对象转换为自定义 struct 需要 1 分钟。
切换到struct 根本没有提高性能。
更新
因此,我删除了 Date 的字符串设置以及对 DateTimes 上的 .ToString() 的调用,性能提高了 1000 倍,与在 @ 上调用 .ToString() 相比,循环在不到 1 秒的时间内执行了 1 分钟。 987654342@。所以,我想我找到了瓶颈,但我可以在这方面使用一些帮助,因为我仍然需要将这些日期传递回网络应用程序。
更新代码
//Removed the setting of the string representations of DateTime's in the `struct`
//no calls to `DateTime.ToString()`
for (int i = 0; i < dl.Count; i++)
{
Structs.StructOnBaseSearchDocument st = new Structs.StructOnBaseSearchDocument()
{
DocumentId = dl[i].ID,
Name = dl[i].Name,
DocumentType = dl[i].DocumentType.Name
//DocStorageDate = dl[i].DateStored.ToString(),
//DocRevisionDate = dl[i].LatestRevision.Date.ToString(),
//DocumentDate = dl[i].DocumentDate.ToString()
};
foundDocs[counter] = st;
counter++;
}
【问题讨论】:
-
您能否提供有关 DLL 的更多信息(可能会发布示例)以及序列化逻辑?
-
@Slothario 在 cmets 中添加了示例代码和解释。
-
是否可以使用 protobuf 之类的东西,或者您是否坚持使用 JSON?
-
@Slothario 这就是我现在的想法,我只是希望有一种方法可以使用我不知道或在研究中发现的类。
-
如果您取得了不错的成绩,请在此处再次发布并告诉我进展如何!
标签: c# asp.net-core