Comments 52
Надеюсь, у вас же правда есть какой-то параметр --force
в таком случае?
Смотря что за скрипт. У некоторых (у полу-одноразовых скриптов, которые действительно предполагается только руками запускать и никак иначе) такого флага нет и даже скрытой возможности запустить из скрипта тоже нет. Но обычно есть какой-то способ запустить её в батч-режиме, да. Иногда это что-то вроде значения типа "i_know_that_i_am_doing_very_bad_thing_and_i_read_documentation" в виде проверки md5(param) = "0d52fbfcafbb4f29983fff89e4184904", где само значение действительно зарыто в документации и его человек может найти, только прочитав документацию достаточно и поняв её.
это не так сложно:
RANDOM_STRING=`xxd -p -l 5 /dev/random`
Не очень понял, зачем этой программе такое мегабыстродействие?
Страшно представить программу которой требуется 3 гигабайта в секунду подтверждений и работает она быстрее чем получает эти подтверждения...
kill --all-humans
?Переработка стандартных инструментов Unix — увлекательное занятие и оно заставляет ценить те изящные трюки, которые делают наши компьютеры быстрыми
Теперь буду говорить на кодревью: "Это не костыль, это изящный трюк!"
По основательности напомнило Копирайт на команду /bin/true
Оптимизации для Бога Оптимизации! Производительности для Трона Производительности!
module Main where
main :: IO ()
main = do
putStrLn yes
yes :: String
yes = 'y' : '\n' : yes
Правда, встроенная `yes` показывает 3.8GiB/s, но это мелочи жизни=)
Твоя программа не реализовывает спецификацию утилиты yes
. В статье написано ведь, что утилита должна принимать аргумент коммандной строки, заменяющий "y"
в случае наличия.
Я вдохновлялся, скорее, наивными реализациями yes
из начала статьи, они тоже не умеют принимать аргументы из командной строки. В любом случае, версия, которая это умеет, ничем по скорости не отличается:
module Main where
import Data.Function (fix)
import System.Environment (getArgs)
main :: IO ()
main = do
args <- getArgs
let str = if null args then "y" else head args
putStr $ fix $ \s -> str ++ "\n" ++ s
www.reddit.com/r/unix/comments/6gxduc/how_is_gnu_yes_so_fast/diua761
Разве для этого не нужен как минимум ~120GHz CPU?
en.wikipedia.org/wiki/Memory_bandwidth#Bandwidth_computation_and_nomenclature
yes | sh boring_installation.sh
А почему тут yes прекращает свой бесконечный цикл и передает управление следующему скрипту в конвейере?
Я всегда думал, что они работают последовательно, сначала первая команда запустится и завершится, запишет выходные данные, затем вторая запустится и прочитает входные данные.
|| — вторая команда выполнится только если статус выхода из первой отличен от нуля
Я всегда думал, что они работают последовательно, сначала первая команда запустится и завершится, запишет выходные данные, затем вторая запустится и прочитает входные данные.Дык эта. Времена MS DOS давно прошли…
Детально не разбирал, но с виду похоже на логику работы gnu версии на Си.
Немного странный пост: всем и так понятно, что наиболее быстрым будет прямой вызов родных методов данной системы (и пачкой отправлять — тоже), что наиболее изящно выглядят на C.
use std::borrow::Cow;
use std::io::{self, Write};
fn main() {
const BUFFER_CAPACITY: usize = 32 * 1024;
let expletive = std::env::args().nth(1)
.map(|s| Cow::Owned(s + "\n"))
.unwrap_or(Cow::Borrowed("y\n"));
let buffer = expletive.repeat(BUFFER_CAPACITY / expletive.len());
let stdout = io::stdout();
let mut handle = stdout.lock();
loop {
handle.write(buffer.as_bytes()).unwrap();
}
}
К тому же, этот вариант, на моей машине, быстрее на 7% быстрее.
У меня при комбинации yes и pv, полученных из репы Ubuntu 16.04 и запущенных как есть,
yes | pv -r > /dev/null
на Lenovo T60 (дрова, ддр2 и T7200) = 1,92 GiB
на Dell M6700 (ddr3 и 3632QM) = 7.58 GiB
А автор до 3 ГБ/с c оптимизированным кодом м трудом добрался.
Что я делаю не так или что я не понял в задаче?
Есть подозрение, что всё очень сильно зависит от частоты памяти. Я скомпилировал свою наивную реализацию на разных машинах и получил разные (в разы, а то на порядки) результаты по скорости.
Не всё так просто, по-моему. На 7-летней давности ноутбуке получаем 7GIB/s:
% yes |pv >/dev/null
^C.6GiB 0:00:05 [7.08GiB/s] [ <=> ]
Model name: Intel(R) Core(TM) i7-2640M CPU @ 2.80GHz
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 4096K
Linux 4.13.0-0.bpo.1-amd64
Type: DDR3
Speed: 1333 MHz
На достаточно новом сервере получаем 0.1GIB/s:
% yes |pv >/dev/null
^C76GiB 0:00:27 [ 108MiB/s] [ <=> ]
Model name: Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 25600K
Linux 4.4.79-1-pve
Type: DDR4
Speed: 2133 MHz
Неужели бывают установщики, которые СТОЛЬКО раз просят у пользователя подтвердить очередную операцию?
Очень интересно описано, но поправьте меня, если не прав, pv считает, сколько через нее прошло (слово "прошло" — условно) за секунду. Если мы отправляем один символ "y", то это около одного символа, а если отправляем буфер, то это около 8k символов — разница почти на 4 порядка по pv скорее показывает, что оба примера работают с одинаковой скоростью в контексте "количества выданных y"
Как выясняется, такая программа работает довольно медленно.
А на третьем питоне еще на 0.5 мб/с медленнее, чем на 2.7 :)
Получилось так
package main
import (
"bufio"
"fmt"
"os"
)
var bufsize = 64 * 1024
func main() {
y := byte('y')
n := byte('\n')
buf := make([]byte, 0x1000)
fmt.Println(bufsize)
for i := 0; i < len(buf)-2; i += 2 {
fmt.Println(i)
buf[i] = y
buf[i+1] = n
}
f := bufio.NewWriterSize(os.Stdout, bufsize)
defer f.Flush()
for {
f.Write(buf)
}
}
Результат:
$ ./yes| pv -r > /dev/null
[9.59GiB/s]
Системный yes выдаёт
$ yes | pv -r > /dev/null
[9.06GiB/s]
package main
import (
"bufio"
"os"
)
var bufsize = 64 * 1024
func main() {
var y []byte
// Get arg
if len(os.Args) > 1 {
y = []byte(os.Args[1] + "\n")
} else {
// Set output to y
y = []byte("y\n")
}
yLen := len(y)
// Create buffer
buf := make([]byte, bufsize)
// Popoulate buffer
for i := 0; i < len(buf)-yLen; i += yLen {
for s := 0; s < len(y); s++ {
buf[i+s] = y[s]
}
}
// Create buffered writer
f := bufio.NewWriterSize(os.Stdout, bufsize)
defer f.Flush()
for {
f.Write(buf)
}
}
скорость не поменялась (да и с чего-бы? :) )
Небольшая история о команде `yes` в Unix