неблокирующая / многопоточная кошка

cat блокирует то, что я вижу в коде , т. е. использует блокировку read() а затем использует блокировку write() .

Я хочу вызвать некоторый инструмент, где я отключу всю буферизацию stdout по назначению (например, как описано здесь ), потому что этот инструмент может вызывать подпроцессы, и я хочу, чтобы все записи из всех подпроцессов на stdout появлялись в одно и то же время, когда они были написаны на в то же время.

Затем я хочу передать этот вывод в многопоточную версию cat (или так). Цель состоит в том, что реальный stdout будет медленным (это файл на диске), но я не хочу, чтобы инструмент зависал, когда он пытается писать на stdout. Если бы я просто сделал

 stdbuf -oL mytool 

то он будет зависать, когда диск занят или так. Когда я делаю

 stdbuf -oL mytool | cat 

Я на самом деле не совсем уверен, что произойдет. Я могу получить дополнительную буферизацию с помощью буфера канала ядра , хотя я думаю, что это не будет использоваться, когда я mytool буферизацию stdout mytool . И тогда stdout cat также будет буферизирован по умолчанию, но в то время, когда cat действительно записывает свою стандартную версию, он может зависать. mytool будет зависать, когда он что-то пишет, а cat не читает одновременно.

Вот почему я ищу многопоточную cat которая читает в то же время, когда она записывается, поэтому запись в stdin multi-threaded-cat никогда не будет блокировать (или только мягкую блокировку или что бы вы ни назвали это ). Он в основном вводит другой буфер в пространстве пользователя в multi-threaded-cat . Когда multi-threaded-cat висит при попытке записи в stdout, это не имеет значения, потому что он все равно будет считываться из stdin параллельно. Поэтому я хочу:

 stdbuf -oL mytool | multi-threaded-cat 

Я хочу, чтобы multi-threaded-cat всегда потребляла входящие данные как можно скорее. Вот почему я думаю, что он, вероятно, должен быть многопоточным. В противном случае, если он использует write (), который может блокировать или хотя бы давать небольшой hickup, а в среднем – while, он не может читать () из stdin.

Я также хочу, чтобы multi-threaded-cat записывала данные как можно скорее. Поэтому он не должен сначала заполнять свой собственный буфер, а затем писать, я хочу, чтобы он записывал всегда сразу.

Мой вариант использования: mytool, включая некоторые подпроцессы, напишет некоторую информацию о регистрации на stdout. stdbuf важен, так что я не получаю никакой задержки в выходе, а также что все подпроцессы stdouts синхронизируются. Все stdout будут перенаправлены в файл журнала на файловом сервере, который немного медленный, и это значительно снизит производительность, когда он будет ждать завершения всех записей. Поэтому я хочу что-то вроде multi-threaded-cat между ними.

Есть ли такой инструмент?

Я просто реализовал свой собственный инструмент здесь . Использование этого уже дает мне ускорение на 800% по сравнению с тем, что его не используют. Но, может быть, есть другие инструменты или другие способы сделать то, что я хочу?

«Multi-threaded» – это деталь реализации, а не то, что вам действительно нужно: многопоточная реализация cat может блокироваться одним потоком, ожидающим другой поток, потому что он ждет, чтобы где-то положить данные, которые он читает. То, что вы ищете, – это неблокирующий cat с потенциально неограниченным буфером.

Утилита sponge из более полезных файлов Joey Hess – это крайняя версия: сначала она считывает весь файл в память, а затем записывает вывод. Это может работать или не работать для вас.

pv позволяет указать размер буфера. У вас не может быть неограниченный буфер, но вы можете установить очень большой максимальный размер (сделайте его размером с памятью, если хотите), буфер выделяется только по требованию.

 stdbuf -oL mytool | pv -q -B 1g >output-file