2008-11-11 17 views
6

Necesitamos desarrollar algún tipo de gestión de búfer para una aplicación que estamos desarrollando utilizando C#.Gestión del conjunto de búfer con C#

Esencialmente, la aplicación recibe mensajes de los dispositivos a medida que entran (puede haber muchos en un corto espacio de tiempo). Necesitamos ponerlos en cola en algún tipo de grupo de búferes para que podamos procesarlos de manera administrada.

Estábamos pensando en asignar un bloque de memoria en trozos de 256 bytes (todos los mensajes son menores) y luego utilizar la administración del grupo de búferes para tener un conjunto de almacenamientos intermedios disponibles que puedan usarse para los mensajes entrantes y un grupo de almacenamientos intermedios listo para ser procesado.

Entonces, el flujo sería "Obtener un búfer" (procesarlo) "Liberar búfer" o "Dejarlo en la piscina". También necesitaríamos saber cuándo se llenó el búfer.

Potencialmente, también necesitaríamos una forma de "echar un vistazo" a los buffers para ver cuál es el búfer de mayor prioridad en el grupo en lugar de obtener siempre el siguiente búfer.

¿Ya hay soporte para esto en .NET o hay algún código fuente abierto que podamos usar?

Respuesta

4

La administración de memoria de C# sharps es en realidad bastante buena, por lo que en lugar de tener un grupo de almacenamientos intermedios, puede asignar exactamente lo que necesita y colocarlo en una cola. Una vez que haya terminado con el búfer, simplemente deje que el recolector de basura lo maneje.

Otra opción (conocer muy poco acerca de su aplicación) es procesar los mensajes mínimamente como los obtiene y convertirlos en objetos completos (con prioridades y todo), entonces su cola podría priorizarlos con solo investigando el conjunto correcto de atributos o métodos.

Si sus mensajes llegan demasiado rápido, incluso para un procesamiento mínimo, podría tener un sistema de dos colas. Uno es solo una cola de almacenamientos intermedios no procesados, y la siguiente cola es la cola de objetos de mensaje construidos a partir de los almacenamientos intermedios.

Espero que esto ayude.

+0

no es una buena idea. cualquier cosa que tenga algo que ver con interoperabilidad causará fragmentación (y dará como resultado excepciones de falta de memoria) debido a que el GC tiene que fijar objetos. –

+2

¿Interopera entre qué? ¿Trapos? Aplicaciones? Procesos? – grieve

+0

Creo que nzpcmad funciona de forma pura sin P/Invoke. – user7116

2

¿Por qué simplemente no recibiría los mensajes, crearía un objeto DeviceMessage (a falta de un mejor nombre) y pondría ese objeto en una cola? Si la priorización es importante, implemente una clase PriorityQueue que maneje eso automáticamente (colocando los objetos DeviceMessage en orden de prioridad a medida que se insertan en la cola). Parece un enfoque más OO, y simplificaría el mantenimiento en el tiempo con respecto a la priorización.

1

Estoy haciendo algo similar. Recibo mensajes sobre hilos de MTA que deben revisarse en hilos de STA.

Usé un BlockingCollection (parte de las extensiones de fx paralelas) que es monitoreado por varios hilos STA (configurable, pero el valor predeterminado es xr * el número de núcleos). Cada hilo intenta mostrar un mensaje fuera de la cola. O bien se desconectan y vuelven a intentarlo o cierran un mensaje y lo mantienen.

Lo tengo conectado con los contadores perfmon para realizar un seguimiento del tiempo de inactividad, las longitudes de trabajo, los mensajes entrantes, etc., que se pueden utilizar para ajustar la configuración de la cola.

Tendría que implementar una colección personalizada, o quizás ampliar BC, para implementar las prioridades de elementos de cola.

Una de las razones por las que lo implementé de esta manera es que, según tengo entendido, queueing theory generalmente favorece una sola línea, múltiples servidores (¿por qué siento que voy a atrapar basura sobre eso?).

2

@grieve: La conexión en red es nativa, lo que significa que cuando se utilizan almacenamientos intermedios en los datos de recepción/envío en la red, estos se fijan en la memoria. ver mis comentarios a continuación para la elaboración.

+0

-1, estoy bastante seguro de que el espacio de nombres de System.Net abstrae todo eso de usted, el usuario final le impide ocuparse de nada de eso. Tampoco veo ninguna mención en el PO que la aplicación utilice interoperabilidad de ningún tipo. – user7116

+1

Quizás no estaba claro: las conexiones de red siempre ocurren en un contexto no administrado, lo que significa que los almacenamientos intermedios que envía a la API de red (que está al final WINSOCK nativo, le guste o no ...) están anclados en la memoria, y no se puede recolectar basura, ni comprimirse (mover en la memoria) cuando el GC intenta comprimir el montón. por lo tanto, ocasiona una gran fragmentación de la memoria y penalizaciones de rendimiento, ya que los almacenamientos intermedios pueden sobrevivir hasta la generación 1 (tal vez incluso gen 2) y afectará al GC, mientras mantiene asignadas más memorias intermedias –

+0

La forma correcta de hacerlo es crear un conjunto de almacenamientos intermedios que le gustaría usar con la red, de modo que la memoria se pierde pero se condensa en un solo lugar y no se ocupará de la administración general del GC, y no volverá a asignar búferes para el espacio de memoria que ya pagó. Por ejemplo, en un ejemplo de servidor web, será prudente tener un caché para los archivos que está sirviendo, manteniendo los almacenamientos intermedios de archivos en memoria y usar estos almacenamientos intermedios cuando use Socket.Send. - Sin asignación o penalización, estos búferes serán válidos durante un tiempo prolongado en casi todos los escenarios de la vida real. –

2

Sé que esta es una publicación anterior, pero creo que debería echar un vistazo al conjunto de memoria implementado en el proyecto ILNumerics. Creo que hicieron exactamente lo que necesitas y es una pieza de código muy bonita. Descargue el código en http://ilnumerics.net/ y eche un vistazo al archivo ILMemoryPool.cs

+0

enlace directo a ILMemoryPool https://ilnumericsnet.svn.sourceforge.net/svnroot/ilnumericsnet/ILNumerics/Misc/ILMemoryPool.cs – Avram