使用 DataContractSerializer 对 WCF 响应进行缓慢序列化
本文关键字:缓慢 序列化 响应 DataContractSerializer WCF 使用 | 更新日期: 2023-09-27 18:30:29
我有一个WCF服务,它执行搜索并向客户端返回相当复杂的对象列表。 这是一个 EAV 系统,因此返回的每个实体都有一个附加的值列表,该值的大小因实体蓝图而异。
在我的测试搜索中,我通过日志记录确认,几乎每种情况下,实际搜索都需要不到一秒钟才能完成。 在将响应返回给客户端之前,我做的最后一件事就是记录处理已完成。
不幸的是,客户端直到我完成响应后 15-20 秒才收到响应。 总响应大小约为 250kb,因此非常小。 目前这是通过LAN传输的,我已经尝试禁用防火墙和防病毒软件以确保两者都不会干扰。
但是,我注意到,如果响应要小得多,例如通过删除附加到每个实体的字段,则响应的完成速度要快得多。 我还尝试单步执行服务的本地托管 (IIS) 副本,在传递最终 return
语句后,仍然需要另外 15 秒才能到达本地客户端应用程序。
我正在使用basicHttpBinding,因为该服务将被.Net和PHP客户端使用。
那么,谁能提出一种方法来确认情况确实如此? 我该如何解决序列化时间过慢的问题?
编辑:
为了澄清,我用 [DataContract] 属性标记了每个类,并使用 [DataMember] 标记了每个属性 - WCF 在返回数据时正在处理序列化。 在本例中,它是类型为"实体"的列表(包含值列表的自定义类。
编辑 2:
我已经测试了 DataContractSerializer 的速度,将 65 个返回实体的列表写入简单的内存流大约需要 15 秒。 这似乎很荒谬,我不确定是什么变化使它如此缓慢。
我已经想通了,这很尴尬。
在测试 DataContractSerializer 的速度时,我使用了从搜索中返回的 65 种产品的列表。 我决定加载数据库中的所有产品(大约 600 个),然后将它们序列化到内存中,但遇到了一些内存不足异常,因此开始将结果写入文本文件。
事实证明,文本文件是1.5GB,大约是整个数据库大小的3倍。 序列化花了 17 秒。 所以实际上,它做得非常好。 正在发生的事情是,每个产品都可以有一个附加实体的列表,并且这些实体也被加载了。 由于它们是序列化的,因此这些实体是重复的,它们在数据库中仅存在一次。
除了去除大量客户不需要的元数据外,我还设法将 50 种产品(原来是 194MB)的列表减少到只有 3MB。 (更新:本周末我将1.5GB列表降至66MB)。
故事的寓意是什么? 倾听社区的声音。 其他人都告诉我 DataContractSerializer 有多快,所以当它对我来说看起来很慢时,我应该责怪自己而不是 DataContractSerializer。
更新:
我花了一些时间试图弄清楚为什么这是一个突然的问题。 答案在于EAV系统的性质-附加到任何实体的数据列表都是动态的。 我最初只在请求单个实体时加载字段数据 - 为了速度,多个实体只加载最低限度。 在我实现缓存后,我将其更改为无论如何加载所有字段数据,但由于复杂的数据模型和大量实体,我没有预料到这会对数据量产生多大影响。 真的,我不应该对我请求的数据量做出任何假设。
你必须使用DataContractSerializer
吗?我发现 DataContractSerializer 在发送大量数据时非常慢,性能损失不是在序列化时,而是在反序列化时。
我们切换到二进制序列化,它的速度要快得多,但它可能与您的PHP客户端不兼容。您可以编写一个可由客户端重用的组件,该组件为您处理反序列化,但对于所有非 .net 客户端,您将遇到此问题。