Una cosa a destacar desde el principio es donde se dice que "la sabiduría convencional ha sido el desarrollo de la tecnología de baja latencia de mensajería requiere el uso de C++ no administrado o lenguaje ensamblador". En particular, están hablando de una especie de caso en el que las personas a menudo descartan una solución .NET (o Java) sin más. En ese caso, una solución de C++ relativamente ingenua probablemente tampoco lo haría.
Otra cosa a considerar aquí, es que esencialmente no se han deshecho tanto del GC como lo han reemplazado - hay código allí administrando la duración del objeto, pero es su propio código.
En su lugar, hay varias maneras diferentes de hacerlo. Aquí hay uno. Supongamos que necesito crear y destruir varios objetos Foo a medida que se ejecuta mi aplicación. creación foo está parametrizado por un int, por lo que el código normal sería:
public class Foo
{
private readonly int _bar;
Foo(int bar)
{
_bar = bar;
}
/* other code that makes this class actually interesting. */
}
public class UsesFoo
{
public void FooUsedHere(int param)
{
Foo baz = new Foo(param)
//Do something here
//baz falls out of scope and is liable to GC colleciton
}
}
Un enfoque muy diferente es:
public class Foo
{
private static readonly Foo[] FOO_STORE = new Foo[MOST_POSSIBLY_NEEDED];
private static Foo FREE;
static Foo()
{
Foo last = FOO_STORE[MOST_POSSIBLY_NEEDED -1] = new Foo();
int idx = MOST_POSSIBLY_NEEDED - 1;
while(idx != 0)
{
Foo newFoo = FOO_STORE[--idx] = new Foo();
newFoo._next = FOO_STORE[idx + 1];
}
FREE = last._next = FOO_STORE[0];
}
private Foo _next;
//Note _bar is no longer readonly. We lose the advantages
//as a cost of reusing objects. Even if Foo acts immutable
//it isn't really.
private int _bar;
public static Foo GetFoo(int bar)
{
Foo ret = FREE;
FREE = ret._next;
return ret;
}
public void Release()
{
_next = FREE;
FREE = this;
}
/* other code that makes this class actually interesting. */
}
public class UsesFoo
{
public void FooUsedHere(int param)
{
Foo baz = Foo.GetFoo(param)
//Do something here
baz.Release();
}
}
Además complicación puede ser añadido si usted está multiproceso (aunque de muy alto rendimiento en un entorno no interactivo, es posible que desee tener un hilo o tiendas separadas de clases Foo por hilo), y si no puede predecir MOST_POSSIBLY_NEEDED por adelantado (lo más simple es crear un nuevo Foo() según sea necesario, pero no liberarlo para GC, que se puede hacer fácilmente en el código anterior creando un nuevo Foo si FREE._next es nulo).
Si permitimos un código inseguro podemos tener ventajas aún mayores al tener Foo a struct (y por lo tanto la matriz que contiene un área contigua de la memoria de la pila), _siguiente puntero a Foo y GetFoo() devolviendo un puntero.
Si esto es lo que estas personas realmente están haciendo, por supuesto no puedo decirlo, pero lo anterior impide que el GC se active. Esto solo será más rápido en condiciones de muy alto rendimiento, si no, dejar que GC haga sus cosas es probablemente mejor (GC realmente lo ayuda, a pesar de que el 90% de las preguntas lo tratan como un Big Bad).
Hay otros enfoques que también evitan GC. En C++, los operadores nuevos y de eliminación pueden anularse, lo que permite cambiar el comportamiento predeterminado de creación y destrucción, y las discusiones sobre cómo y por qué uno podría serlo podrían interesarle.
Una práctica para llevar a cabo es cuando los objetos contienen recursos que no son de memoria que son caros (por ejemplo, conexiones a bases de datos) o "aprender" a medida que se utilizan (por ejemplo, XmlNameTables). En este caso, la agrupación de objetos es útil (las conexiones ADO.NET lo hacen de forma predeterminada). En este caso, aunque una cola simple es el camino a seguir, como la sobrecarga adicional en términos de memoria no importa. También puede abandonar objetos en contención de bloqueo (está buscando obtener rendimiento, y la contención de bloqueo lo dañará más que abandonar el objeto), lo que dudo que funcione en su caso.
¿Realmente * necesita * para hacer esto? La mayoría de los sistemas casi en tiempo real simplemente usan código no administrado. –
No, NO NECESITO hacerlo. Pero me encantaría saber cómo. – Carlos