Cómo desactivar el mecanismo de recolección de COM

Resumen

Mecanismo de recolección automática de COM permite a los objetos en los servidores COM para reclamar sus asignaciones de recursos y eliminarse a sí mismos en caso de que todos los clientes termina de forma anormal. Periódicos pings enviados desde cada equipo cliente para cada equipo servidor implica la aplicación de este mecanismo. Hay algunas situaciones donde podría ser conveniente desactivar el comando ping para crear un objeto COM "/NOPING". En este artículo se describe estas situaciones y también muestra un método mediante el cual un servidor COM puede desactivar comandos ping para sus objetos.

Más información

Cuando un cliente COM termina normalmente, libera todas las referencias a su objeto de servidor. Cuando un cliente finaliza correctamente sin embargo, puede haber referencias pendientes al objeto de servidor. Sin un mecanismo de recolección, el código del servidor no tiene forma de saber cuándo se deben reclamar los recursos asignados para el objeto COM, que puede provocar una pérdida de recursos. Para solucionar este problema, COM implementa un mecanismo de recolección automática en la que el proceso de resolución de COM (RPCSS) en el equipo cliente hace ping en el equipo del servidor en nombre del proceso del cliente.

Una descripción detallada de la estrategia general de basura colección (GC) y el protocolo de COM queda fuera del alcance de este artículo. Hay, sin embargo, muchas optimizaciones implicadas, tal que la sobrecarga de ping incluso en un sistema DCOM a gran escala es extremadamente baja. Las optimizaciones más básicas son que el tráfico de ping (a) se produce en equipo a equipo, no en forma de objeto de cliente o en una base de proceso a proceso; (b) todas las referencias de todos los clientes a todos los objetos se resumen en un solo 128-bit value (un "ping conjunto ID"), con sólo ese valor de 16 bytes que se envían a través de la red cada dos minutos. En otras palabras, en un estado estable, un cliente mantiene una referencia a un objeto en un servidor generará la misma cantidad pequeña de tráfico de ping como 1.000 clientes mantengan 10.000 referencias a 10.000 objetos en el mismo servidor. (Un mensaje ping ligeramente mayor se envía para agregar o quitar objetos de ping establecida como el conjunto de referencias varía con el tiempo). Por otra parte, alternativas al uso de protocolo de GC de COM (por ejemplo, utilizando el nivel de aplicación periódica "ping"--llamadas a métodos que informan sobre el objeto que los clientes están aún vivos o utilizando un subyacente de transporte mecanismo como TCP keepalives) son demostrable mucho menos eficaz. Por lo tanto, el mecanismo de GC de DCOM predeterminado debe utilizarse para cualquier objeto que se debe apagar cuando sus clientes desaparecen o de lo contrario se comporten mal si esos objetos se convertiría efectivamente las pérdidas de memoria en el servidor.

La resolución en el equipo servidor realiza un seguimiento de los ping para cada objeto de servidor. El período de ping es de 2 minutos y, actualmente, es no-configurable. Cuando la resolución en el servidor detecta que un objeto no ha sido hacer ping durante 6 minutos, se supone que todos los clientes del objeto han finalizado o que ya no utiliza el objeto lo contrario. La resolución suelte todas las referencias externas al objeto. Para ello, basta con que el Administrador de código auxiliar del objeto (COM en tiempo de ejecución código que ofrece llamadas a cada objeto) llame a:: Release() en la interfaz IUnknown del objeto. En este momento, recuento de referencias del objeto será cero, así que lo que se refiere el tiempo de ejecución COM. (Puede haber referencias mantenidas por los clientes locales (mismo apartamento), así que el recuento de referencia interna del objeto no puede ir necesariamente a cero en este momento.) El objeto puede, a continuación, cerrarse.

NOTA: recolección se aplica a todos los servidores independientemente de si sus clientes son local o remoto, o una combinación de local y remoto. El mecanismo de ping subyacente es distinto en el caso local como no se generan paquetes de red, pero para todos los propósitos prácticos, el comportamiento es el mismo.

Hay algunas circunstancias donde es aconsejable desactivar el mecanismo de recolección de COM. Por ejemplo, podría tener un objeto sin estado (por ejemplo, un usuario múltiples computacional objeto donde todo Estado pertinente se pasa como parámetros [in] en llamadas a métodos y el resultado correspondiente se proporciona como un parámetro [out]) o un objeto de larga duración con ningún estado de la relación de cliente (por ejemplo, los objetos que componen un directorio de otros objetos) que no tiene la capacidad de detectar la vitalidad de sus clientes. Básicamente, el tipo de objeto de discusión es aquel en el que la implementación interna de la IUnknown:: AddRef y:: Release() métodos no controlan la vida del objeto; otro mecanismo se utiliza para determinar cuándo se debe cerrar el objeto (si es que alguna vez). En tales situaciones, puede ser preferible desactivar el ping periódico para eliminar el tráfico de red que causen. La sección siguiente muestra cómo hacerlo mediante código de ejemplo.

Debe tenerse en cuenta que la recolección se realiza en forma de objeto y no sobre una base por proceso. Por lo tanto, si tiene un proceso de servidor sirve a varios objetos (incluidos los objetos de la fábrica de clase) a todos los clientes y no desea que el equipo del servidor al que se hacer ping por sus clientes, debe desactivar la opción de hacer ping para todos los objetos en el servidor. Como corolario, aunque es perfectamente válido para deshabilitar comandos ping para sólo uno o algunos objetos en un proceso o para todos los objetos en uno o sólo algunos procesos en un servidor, el protocolo ping COM tan optimizado que no habrá ningún cambio significativo en el ancho de banda de red utilizado por el protocolo de GC de COM si hay alguno o 10.000 objetos DCOM en uso en todo el equipo--suponiendo que todos los objetos tienen aproximadamente el mismo número y conjunto de clientes. En otras palabras, si hay otros objetos DCOM en un servidor determinado mediante el protocolo de GC/ping de COM, y se utilizan esos objetos por aproximadamente el mismo número y un conjunto de clientes que utilizan un objeto que puede calcular las referencias "/NOPING", hay esencialmente ninguna ventaja a desactivar el protocolo ping con respecto a ese objeto concreto. Sólo habrá una disminución mensurable en el tráfico de red si los clientes de los objetos /NOPING son significativamente diferentes de los clientes de los otros objetos en el mismo equipo.

Asimismo, debe tenerse cuidadosamente que recolección es una proposición de todo o nada. Si desactiva recolección para un objeto, a continuación, administración de duración basada en COM del objeto se desactiva también. Esto significa que los clientes ya no pueden llamar a Release() en sus punteros de interfaz y se espera que el objeto de recibir la llamada. Release() llamada en cualquier proxy es una operación inefectiva para dichos objetos. Esto puede parecer poco intuitiva al principio, pero es el comportamiento correcto, ya que COM ya no puede garantizar que el objeto se cerrará cuando desaparecen los clientes. Si:: Release() se habilitó en esta situación, a continuación, el objeto encontraría que su recuento de referencias se fueron a cero cuando todos los clientes se comportaban correctamente pero nunca fueron a cero si todo cliente ha respondido correctamente. Este tipo de comportamiento no totalmente confiable es mucho peor que la regla sencilla que si se calculan las referencias de objetos con el indicador /NOPING entonces sin excepción nunca recibirán cualquiera:: Release() llamadas desde el tiempo de ejecución COM. Como un detalle de implementación, para maximizar la eficacia de la red:: Release() llama en los servidores proxy para los objetos cuyas referencias se calculan /NOPING nunca se envían a través del cable.

Código de ejemplo

Puede desactivar la recolección y ping para un objeto mediante el cálculo de referencias sus interfaces con el indicador MSHLFLAGS_NOPING. El código de ejemplo siguiente muestra cómo hacerlo en función de la fábrica clase CreateInstance(). Esto es necesario para que el objeto de contador de referencias estándar obtiene asociado con el Administrador de código auxiliar para el objeto en cuanto se crea el objeto. Las subsiguientes llamadas a CoMarshalInterface() por el Administrador de código auxiliar encontrará el objeto de contador de referencias estándar creados previamente.
  STDMETHODIMP  CClassFactory::CreateInstance(LPUNKNOWN punkOuter, REFIID riid,
void**ppv)
{
HRESULT hr;
IMarshal *pIM = NULL;
IUnknown *pUnknown;

*ppv = NULL;
if (punkOuter != NULL)
return CLASS_E_NOAGGREGATION;

// create our object.
p = new CSimpleObject;
if (p == NULL)
return E_OUTOFMEMORY;

hr = p->QueryInterface(IID_IUnknown, (void**)&pUnknown);
hr = CoGetStandardMarshal(riid, pUnknown, 0, NULL, MSHLFLAGS_NOPING
|MSHLFLAGS_NORMAL, &pIM);

// don't release pIM. All marshals of all interfaces on this object
// from now on will automatically be NOPING

if (FAILED(hr))
{
Message(TEXT("Server: CoGetStandardMarshal Error"), hr);
return(E_FAILED);
}
pUnknown->Release();

hr = p->QueryInterface(riid, ppv);
return hr;
} // CClassFactory::CreateInstance

Propiedades

Id. de artículo: 171414 - Última revisión: 01/09/2017 - Revisión: 1

Comentarios