Существуют ли Groovy трубы реальных UNIX-труб?

Я просто начал сегодня смотреть в Groovy. Я считаю, что использовать его для замены некоторых из моих более сложных сценариев bash.

Одной из его очень интересных концепций для меня является возможность легко использовать трубы:

proc1 = 'ls'.execute()
proc2 = 'tr -d o'.execute()
proc3 = 'tr -d e'.execute()
proc4 = 'tr -d i'.execute()
proc1 | proc2 | proc3 | proc4
proc4.waitFor()

Это потрясающе. Но мой вопрос: использует ли это реальные UNIX-каналы (например, в Linux), или это просто симуляция с потоками Java? (И если да, то это намного медленнее/более неэффективно?)

Ответ 1

Из-за перегрузки оператора он в конечном итоге вызывает ProcessGroovyMethods.pipeTo() в среде выполнения Groovy, которая действительно имитирует каналы с использованием java потоки:

    /**
     * Allows one Process to asynchronously pipe data to another Process.
     *
     * @param left  a Process instance
     * @param right a Process to pipe output to
     * @return the second Process to allow chaining
     * @throws java.io.IOException if an IOException occurs.
     * @since 1.5.2
     */
    public static Process pipeTo(final Process left, final Process right) throws IOException {
        new Thread(new Runnable() {
            public void run() {
                InputStream in = new BufferedInputStream(getIn(left));
                OutputStream out = new BufferedOutputStream(getOut(right));
                byte[] buf = new byte[8192];
                int next;
                try {
                    while ((next = in.read(buf)) != -1) {
                        out.write(buf, 0, next);
                    }
                } catch (IOException e) {
                    throw new GroovyRuntimeException("exception while reading process stream", e);
                } finally {
                    closeWithWarning(out);
                }
            }
        }).start();
        return right;
    }

Я не могу говорить о количестве накладных расходов, связанных с верхней частью моей головы.

Ответ 2

Я нашел groovy моделирование труб намного медленнее, чем unix-каналы:

Bash команда

zcat dump.sql.gz | mysql -u${mysql_user} --password=${mysql_password} -D${db_name} 

Занимает около 40 минут

То же самое с groovy

def proc1 = ["zcat", "${sqlGzFile.getPath()}"].execute()
def proc2 = ["mysql", "-u${mysqlUser}", "--password=${mysqlPassword}", "-D$dbName"].execute()   
proc1 | proc2
proc2.waitFor()

занимает около 2 часов и 40 минут

Но вы можете делать трубы с помощью:

def proc = ["sh", "-c",  "zcat dump.sql.gz | mysql -u${mysql_user} --password=${mysql_password} -D${db_name}"].execute()
proc.waitFor()

Ответ 3

Groovy не может использовать Unix-каналы, потому что необходимо подключить Unix-каналы до того, как будут запущены дочерние процессы. Но ваш пример сначала запускает весь процесс и связывает их с трубами позже.

Кроме того, Groovy должен был бы вызвать некоторые системные вызовы манипуляции с файлами (dup, dup2), которые недоступны в JVM без использования дополнительной библиотеки.