Análise fragmentada com FParsec
Pergunta
É possível enviar entrada para um analisador FParsec em blocos, a partir de um soquete? Se não, é possível recuperar o resultado atual e a parte não analisada de um fluxo de entrada para que eu possa fazer isso? Estou tentando executar os blocos de entrada vindos de SocketAsyncEventArgs
sem armazenar em buffer mensagens inteiras.
<"Atualizar
O motivo para observar o uso de SocketAsyncEventArgs
foi para denotar que o envio de dados para um CharStream
pode resultar em acesso assíncrono ao Stream
subjacente. Especificamente, estou pensando em usar um buffer circular para enviar os dados vindos do soquete. Lembro-me da documentação do FParsec observando que o Stream
subjacente não deve ser acessado de forma assíncrona, então planejei controlar manualmente a análise fragmentada.
Perguntas finais:
- Posso usar um buffer circular no meu
Stream
passado para oCharStream
? - Não preciso me preocupar em controlar manualmente a fragmentação neste cenário?
Solução
A versão normal do FParsec (embora não o Baixo -Versão confiável ) lê a entrada em blocos, ou "blocos", como eu chamo em documentação CharStream
. Portanto, se você construir um CharStream
a partir de um System.IO.Stream
e o conteúdo for grande o suficiente para abranger vários blocos CharStream
, você pode começar a analisar antes de recuperar totalmente a entrada.
Observe, no entanto, que o CharStream
consumirá o fluxo de entrada em blocos de tamanho fixo (mas configurável), ou seja, ele chamará o método Read
do System.IO.Stream
quantas vezes for necessário para preencher um bloco completo. Portanto, se você analisar a entrada mais rápido do que pode recuperar uma nova entrada, o CharStream
pode bloquear mesmo que já haja alguma entrada não analisada, porque ainda não há entrada suficiente para preencher um bloco completo.
< Budapate
A (s) resposta (s) para suas perguntas principais: 42.
-
A forma como você implementa o
Stream
a partir do qual constrói oCharStream
depende inteiramente de você. A restrição que você está lembrando que exclui o acesso paralelo se aplica apenas à classeCharStream
, que não é thread-safe. -
A implementação do
Stream
como um buffer circular provavelmente restringe a distância máxima na qual você pode retroceder. -
O tamanho do bloco do
CharStream
influencia o quanto você pode retroceder quando oStream
não oferece suporte à busca. -
A maneira mais simples de analisar a entrada de forma assíncrona é fazer a análise em uma tarefa assíncrona (ou seja, em um thread de segundo plano). Na tarefa, você pode simplesmente ler o soquete de forma síncrona ou, se não confiar no armazenamento em buffer do sistema operacional, pode usar uma classe de fluxo como o
BlockingStream
descrito no artigo que você vinculou no segundo comentário abaixo. -
Se a entrada puder ser facilmente separada em pedaços independentes (por exemplo, linhas para um formato de texto baseado em linha), pode ser mais eficiente dividir você mesmo e, em seguida, analisar o pedaço de entrada por pedaço.