【问题标题】:Cross process COM Marshaler: reduce number of copies for large arrays跨进程 COM Marshaler:减少大型数组的副本数
【发布时间】:2014-02-24 05:22:09
【问题描述】:

作为简化案例:我需要通过现有的 COM 接口将 VARIANT 传输到另一个进程。我目前使用 MIDL 生成的编组器。

实际传输用于许多值,是时间关键过程的一部分,并且可能涉及大字符串或安全数组(几 MB),因此复制的数量似乎相关。

由于接收方需要在函数调用之外“保留”数据,因此封送拆收器至少需要制作一份副本。但是,我能想到的所有签名都包含两个副本:

SetValue([in] VARIANT)
GetValue([out] VARIANT *)  // called by receiver

在这两种情况下,据我了解,编组器会制作一个跨进程副本,该副本确实会被编组器破坏。由于我需要将数据保存在接收器中,因此我需要制作第二份副本。

我考虑在接收器“分离”数据:

SetValue([in, out] VARIANT *)  
    // receiver detaches value and sets to VT_EMPTY for return

但这也会破坏源。

Q1:是否可以让 MIDL 生成的编组代码只执行一份副本?
Q2:这可以通过自定义编组器实现吗?以什么代价? (我第一次看到这非常令人沮丧)

我很想使用 SAFEARRAY 和/或其他 VARIANT/PROPVARIANT 类型,并传输整个数组。

[编辑]

双方都使用 C++,接口都是基于 IUnknown 的,并且需要在同一台机器上跨进程工作,在相同的上下文中。

【问题讨论】:

  • 发送方(客户端)调用SetValue,接收方(服务器)实现。这里是否有一些您没有提供的细节,例如发送者和接收者都是另一个远程对象的客户端?如果需要在中间有这样一个远程对象的两个实体之间进行传输,可以使用SetValue([in] IMyArray *)GetValue([out] IMyArray **) 其中IMyArray 然后有GetArray([out] VARIANT *)。然后,接收方可以直接向发送方索取数组。
  • 问题 1:这是否需要自动化兼容(即,可以从不同的语言调用)?如果是这样,你可能不走运。
  • 问题 2:这必须跨机器工作,还是只在单台机器上跨进程工作?如果只是跨进程,那么编组会变得简单得多(您不需要构建花哨的线格式等)。
  • @EricBrown:查看更新,在一台机器上是 IUnknown。
  • @acelent:问题 - 至少据我所知 - 是编组器需要制作副本,并且没有办法告诉它不要释放它。这迫使我拥有第二份副本。

标签: c++ windows com marshalling


【解决方案1】:

您没有这么明确地说,但您要解决的问题似乎是速度问题。在任何情况下,如果您还没有这样做,请考虑使用分析器来识别瓶颈

在这种情况下,我非常怀疑是复制需要时间。相反,它可能是所涉及的进程之间的上下文切换,因为您一次获得一个值。这意味着对于您检索的每个值,您必须将进程切换到调用的目标,然后再次切换回来。

在设置或获取多个值时,您可以极大地加快这一速度,让您的设计不那么“喋喋不休”。

类似这样的:

SetMultipleValues(
[in] SAFEARRAY(BSTR)* asNames,
[in] SAFEARRAY(VARIANT)* avValues
)

GetMultipleValues(
[in] SAFEARRAY(BSTR)* asNames,
[out,retval] SAFEARRAY(VARIANT)* pavValues
)

即调用GetMultipleValues时,传入一个包含10个名字的数组,并按照传入的名字顺序接收一个包含10个值的数组(如果值不存在,则为VT_EMPTY)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-03
    • 2012-08-26
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2016-09-19
    • 2023-02-24
    • 1970-01-01
    相关资源
    最近更新 更多