Re: Вопросов накопилось по работе с буферами. И как оптимально буферизовать весь исходящий поток внутри фильтра?

Maxim Dounin mdounin на mdounin.ru
Чт Дек 2 19:40:29 MSK 2010


Hello!

On Thu, Dec 02, 2010 at 07:13:21PM +0300, Валентин Бартенев wrote:

> 
> > > Как сделал я. Я создаю первый буфер, его размер всегда известен заранее и
> > > копирую туда данные из приходящих in chains, пока он не заполнится. Также
> > > я решил сделать небольшую оптимизацию, в случае, если все необходимые
> > > для него данные и так содержатся в пределах одного пришедшего буфера, я
> > > использую его, вместо создания своего и копирования туда.
> > > 
> > > И тут первый вопрос возник. Я обнаружил, что таким образом я блокирую
> > > механизм повторного использования освобожденных буферов в
> > > ngx_output_chain, которую передо мной вызывает copy-фильтр. Вызывается
> > > функция ngx_chain_update_chains, которая в случае использования мной
> > > первого пришедшего буфера в итоге всегда делает break на первой же
> > > итерации. Получается фиговая оптимизация, и лучше в моем случае всегда
> > > копировать данные в свой созданный буфер, или эту пустяки?
> > 
> > На основе этого описания мне трудно понять что там происходит, но могу
> > предположить, что после копирования пришедшего буфера Вы не обновляете
> > указатель buf->pos до buf->last. Таким образом copy-фильтр думает, что эти
> > данные всё ещё не обработаны и они зависают в busy.
> 
> Разумеется, если я буфер копирую, то buf->pos = buf->last у переданных фильтру 
> буферов. Но чтобы избежать лишней операции копирования, в довольно 
> распространенном случае, когда нужное единым куском и так пришло в одном 
> буфере, то использую этот самый буфер. Естественно, в этом случае, buf->pos 
> остается указывать на начало. Буфер, как раз, в этом случае не обработан, он 
> мне нужен до самого конца.

Если один буфер задержан - то следующих никто не обещал.  Так что 
если обработать сразу возможности нет, то только копировать.

> Вроде бы все хорошо, но вот последующие данные (для второго буфера) довольно 
> часто приходят в нескольких буферах, и их уже приходится копировать. По идее 
> они свободны, у них buf->pos = buf->last, но они дальше висят в busy, из-за 
> первого буфера.
> 
> Тут дилемма, либо всегда копировать данные к себе, и таким образом освобождать 
> все приходящие буфера, либо оставить, как сейчас сделано, но тогда, ни один 
> буфер не освободится, пока фильтр полностью не отработает, не сгенерирует 
> новый поток данных.

Тут нет делеммы: если вы хотите чтобы работало, то буфера надо 
освобождать.  В противном случае при output_buffers 1 4k; и/или 
proxy_buffering off; и/или proxy_buffers 1 4k и т.п. - всё просто 
сломается, ибо следующий буфер просто не придёт.

Maxim Dounin



Подробная информация о списке рассылки nginx-ru