J'ai créé une classe de gestionnaire de tampons simple à utiliser avec les sockets asynchrones. Cela protégera contre la fragmentation de la mémoire et améliorera les performances. Des suggestions pour d'autres améliorations ou d'autres approches?Suggestions pour un gestionnaire de tampons non bloquants sûrs pour les threads
public class BufferManager
{
private int[] free;
private byte[] buffer;
private readonly int blocksize;
public BufferManager(int count, int blocksize)
{
buffer = new byte[count * blocksize];
free = new int[count];
this.blocksize = blocksize;
for (int i = 0; i < count; i++)
free[i] = 1;
}
public void SetBuffer(SocketAsyncEventArgs args)
{
for (int i = 0; i < free.Length; i++)
{
if (1 == Interlocked.CompareExchange(ref free[i], 0, 1))
{
args.SetBuffer(buffer, i * blocksize, blocksize);
return;
}
}
args.SetBuffer(new byte[blocksize], 0, blocksize);
}
public void FreeBuffer(SocketAsyncEventArgs args)
{
int offset = args.Offset;
byte[] buff = args.Buffer;
args.SetBuffer(null, 0, 0);
if (buffer == buff)
free[offset/blocksize] = 1;
}
}
Excellentes suggestions! D'abord, j'ai décidé d'utiliser un tampon large pour protéger contre la fragmentation de la mémoire. Mais peut-être que cela n'a pas d'importance quand tous les octets seront attribués en même temps. – remdao
La fragmentation ne devient vraiment un problème qu'avec des tampons supérieurs à environ 80 Ko puisque seules les allocations de 80 Ko ou plus sont prises dans le tas d'objets Large qui ne reçoit pas de compactage. Toute chose provient moins du tas normal que le GC compactera après la collecte, éliminant ainsi toute fragmentation. – AnthonyWJones
J'ai réalisé qu'il est probablement préférable d'implémenter le gestionnaire de tampons sous la forme d'une pile de tableaux d'octets.Parce que s'il n'a pas à suivre les offsets, il n'y a pas de raison d'avoir une boucle. Il sera plus rapide de pousser et de faire éclater les objets du tableau d'octets. – remdao