atraso microssegundo necessidade em .NET app para estrangular taxa de transmissão de multicast UDP
Pergunta
Eu estou escrevendo um par cliente / servidor multicast UDP em C # e eu preciso de um atraso na ordem de 50-100 ms (microssegundos) para estrangular a taxa de transmissão do servidor. Isso ajuda a evitar a perda de pacote significativo e também ajuda a evitar sobrecarregar os clientes que estão disco I / O bound. Por favor, não sugerem Thread.Sleep ou Thread.SpinWait. Eu não iria perguntar se eu precisava de um desses.
Meu primeiro pensamento era usar algum tipo de contador de alta performance e fazer um simples loop while () verificar o tempo decorrido mas eu gostaria de evitar que, como ele se sente kludgey. Não que também peg a utilização da CPU para o processo do servidor?
Os pontos de bónus para uma solução multi-plataforma, ou seja, não o Windows específica. Agradecemos antecipadamente, guys!
Solução
Gostaria de usar cronômetro mas seria necessário um laço
este para adicionar mais extensão para o cronômetro, como ElapsedMicroseconds
ou algo como este trabalho poder demasiado
System.Diagnostics.Stopwatch.IsHighResolution deve ser verdade
static void Main(string[] args)
{
Stopwatch sw;
sw = Stopwatch.StartNew();
int i = 0;
while (sw.ElapsedMilliseconds <= 5000)
{
if (sw.Elapsed.Ticks % 100 == 0)
{ i++; /* do something*/ }
}
sw.Stop();
}
Outras dicas
tempos de sono muito curtos são geralmente melhor alcançada por um loop de rotação de CPU (como o tipo que você descreve). Você geralmente quer evitar o uso das chamadas temporizador de alta precisão como eles próprios podem ocupar o tempo e distorcer os resultados. Eu não me preocuparia muito com CPU atrelar no servidor para esses tempos curtos de espera.
Gostaria de encapsular o comportamento em uma classe, como a seguir:
- Crie uma classe cujo construtor estático é executado um ciclo de centrifugação durante vários milhões de iterações e capturas de quanto tempo leva. Isso lhe dá uma idéia de quanto tempo um único ciclo de loop iria assumir o hardware subjacente.
- Compute um uS / iteração valor que você pode usar para calcular tempos de sono arbitrária.
- Quando lhe pediram para dormir por um determinado período de tempo, nos dividir para dormir pelo valor de uS / iteração previamente calculado para identificar quantas iterações de loop para executar.
- rotação usando um loop while até que os decorrido tempo estimado.
Eu experimentei com essa exigência quando eu precisava de mais precisão com o meu pedido multicast.
Descobri que os melhores reside solução com os temporizadores multimédia como visto em neste exemplo .
Eu usei essa implementação e acrescentou TPL assíncrono invocar a ele. Você deve ver meu projeto SimpleMulticastAnalyzer para obter mais informações.
static void udelay(long us)
{
var sw = System.Diagnostics.Stopwatch.StartNew();
long v = (us * System.Diagnostics.Stopwatch.Frequency )/ 1000000;
while (sw.ElapsedTicks < v)
{
}
}
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("" + i + " " + DateTime.Now.Second + "." + DateTime.Now.Millisecond);
udelay(1000000);
}
}
Você já olhou para multimídia timers ? Você provavelmente poderia encontrar um lugar biblioteca .NET que envolve as chamadas de API em algum lugar.
Eu iria desencorajar utilizando loop rodada, uma vez que consome e cria bloqueando fio. Thread.sleep é melhor, ele não usa recursos do processador durante o sono, ele só cortar o tempo. Experimente, e você vai ver a partir gerenciador de tarefas como o uso de CPU pico com o ciclo de centrifugação.