Как записать, что повторная свободная форма представляет в виде строки в файл, с такой скоростью, как 'dd'?

Существует несколько способов выполнить это. Самое легкое должно, вероятно, настроить то, что известно как демилитаризованная зона. Больше безопасного пути, однако, находится на Вашем маршрутизаторе для установки статического маршрута на порте 22 к IP сервера.

Ресурсы:

6
10.03.2018, 17:29
8 ответов
$ time perl -e \
    '$count=1024*1024; while ($count>0) { print "x" x 384; $count--; }' > out
real    0m1.284s
user    0m0.316s
sys 0m0.961s
$ ls -lh out
-rw-r--r-- 1 me group 384M Apr 16 19:47 out

Замена "x" x 384 (который производит строку 384 xs) с чем Вам нравится.

Можно оптимизировать это далее при помощи большей строки в каждом цикле и обхода нормального стандарта, буферизующего.

$ perl -e \
   '$count=384; while ($count>0) {
      syswrite(STDOUT, "x" x (1024*1024),  1024*1024);
      $count--;
    }' > out

В этом случае, syswrite вызовы передадут 1M за один раз к базовому write syscall, который становится довольно хорошим. (Я обхожу 0,940 пользователей с с этим.)

Подсказка: удостоверьтесь, что Вы звоните sync между каждым тестом, чтобы не иметь сбрасывание предыдущего выполнения вмешиваются во ввод-вывод текущего выполнения.

Для ссылки я добираюсь на этот раз:

$ time dd if=/dev/zero bs=1024 count=$((1024*384)) of=./out
393216+0 records in
393216+0 records out
402653184 bytes (403 MB) copied, 1.41404 s, 285 MB/s

real    0m1.480s
user    0m0.054s
sys 0m1.410s
5
27.01.2020, 20:24
  • 1
    Интересный и полезный.. Поскольку длина строки уменьшает, увеличения времени.. На моем поле Ваша точная команда взяла real/user/sys **0m4.565s**/0m0.804s/0m0.904s .. со строкой "x\n", это взяло r/u/s **0m30.227s**/0m29.202s/0m0.880s... но это все еще, конечно, быстрее, чем printf--sed ... 384 версии строки байтов о той же скорости как dd в моей системе также... (это забавно, как варьируются вещи... Я на самом деле получил более медленную dd скорость на этот раз... –  Peter.O 16.04.2011, 22:48
  • 2
    , который я включал несколько тестовых раз в свой ответ (так, чтобы все случаи коснулись тех же аппаратных средств). –  Peter.O 18.04.2011, 12:59

Обычно ожидается, что оболочки медленные при обработке больших частей данных. Для большинства сценариев Вы знаете заранее, какие биты данных, вероятно, будут маленькими и какие биты данных, вероятно, будут большими.

  • Предпочтите полагаться на оболочку, созданную-ins для маленьких данных, потому что разветвление и exec'ing внешний процесс вызывает постоянные издержки.
  • Предпочтите полагаться на внешние, специальные инструменты для больших данных, потому что скомпилированные инструменты специального назначения более эффективны, чем интерпретируемый язык общего назначения.

dd делает read и write вызовы, которые используют размер блока. Можно наблюдать это с strace (или связка, трассировка, … в зависимости от ОС):

$ strace -s9 dd if=/dev/zero of=/dev/null ibs=1024k obs=2048k count=4
✄
read(0, "\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
read(0, "\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
write(1, "\0\0\0\0\0\0\0\0\0"..., 2097152) = 2097152
read(0, "\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
read(0, "\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
write(1, "\0\0\0\0\0\0\0\0\0"..., 2097152) = 2097152
✄

Большинство других инструментов имеет намного более низкое ограничение на максимальном размере буфера, таким образом, они сделали бы больше syscalls, и следовательно занимать больше времени. Но обратите внимание, что это - нереалистичный сравнительный тест: если бы Вы писали в регулярный файл или канал или сокет, то ядро, вероятно, не записало бы больше, чем несколько килобайтов в syscall так или иначе.

2
27.01.2020, 20:24
  • 1
    Другой ответ inciteful, спасибо... Мне действительно нравятся Ваши принципы пункта маркированного списка о том, когда "Предпочесть".... Я начинаю дифференцироваться между созданной-ins оболочкой и внешним обликом... У меня есть близко к законченному свой альтернативный метод.. это - скорость, очень близко dd, и, кажется, довольно равнодушен к размеру строки... (Я попытаюсь отправить его когда-то завтра, после того как я получаю его аккуратный :)... –  Peter.O 16.04.2011, 22:37
  • 2
    @fred.bear, записывая подсказку: Я предполагаю, что Вы имели в виду "проницательный", а не "inciteful" (который не существует, но мог быть связан с, "для подстрекательства"). приложения –  asoundmove 17.04.2011, 00:48
  • 3
    @asoundmove:Спасибо. я довольно доволен такими предупреждениями.. но я определенно(?) имел в виду 'inciteful' :) oxforddictionaries.com/view/entry/m_en_gb0404940#m_en_gb0404940 (но не подстрекать к незаконной деятельности, поскольку строгий смысл слова подразумевает... У меня может быть два соединенные проводом креста.. Я вспоминаю оба чувства; "понимание" и "быть подстрекаемым"... На самом деле признаю я.. Эй, :) мое оправдание: не много сна вчера вечером. слишком много Вопросы и ответы.... Я думаю, что действительно имел в виду главным образом "понимание".. но я определенно вспоминаю размышление об обоих словах. (немного вне темы, но изменение так же хорошо как праздник :) –  Peter.O 17.04.2011, 01:40
  • 4
    @fred.bear: о, это действительно существует! Новый на мне. Изучайте что-то новое каждый день. –  asoundmove 17.04.2011, 06:43

Версия Python:

import sys

CHAR = sys.argv[1] if len(sys.argv) > 1 else "x"

block = CHAR * 1024
count = 1024 * 384

with open("testout.bin", "w") as outf:
    for i in xrange(count):
        outf.write(block)

python2.7 writestr.py x
0,27 пользователя с 0,69 системных общих количества cpu 0.963 99% с

dd, если =/dev/zero of=testout.bin bs=1024 count= $ ((1024 *384))
0,05 пользователя с 1,05 системных общих количества cpu 1.167 94% с

Python стоили более высокой инициализации, но полного удара dd в моей системе.

1
27.01.2020, 20:24
  • 1
    Это выглядит очень хорошим.. Это думает, что фактическое количество повторений (xrange) зависело бы от системных ресурсов, но это может добраться, несколько ГБ строк от одного только xrange... (легко имел дело с остроумием немного проверки границ)... Я включал несколько тестовых раз в свой ответ.. И Ваш метод и мой метод близко к 'dd', timewise.. –  Peter.O 18.04.2011, 00:51

Я наконец надел свою идею, как сделать эту работу... Это использует a tee |tee |tee цепочка, которая работает в близко к ddскорость..

# ============================================================================
# repstr
#
# Brief:
#   Make multiple (repeat) copies of a string.
#   Option -e, --eval is used as in 'echo -e'
#
# Return:
#   The resulting string is sent to stdout
#
#   Args:       Option      $1         $2
#             -e, --eval   COUNT      STRING
#     repstr             $((2**40))    "x"       # 1 TB:     xxxxxxxxx...
# eg. repstr  -e            7         "AB\tC\n"  # 7 lines:  AB<TAB>C
#     repstr                2         "ऑढळ|a"   # 2 copies:  ऑढळ|aऑढळ|a 
#

[[ "$1" == "-e" || "$1" == "--eval" ]] && { e="-e"; shift 1; }|| e=""
 count="$1"
string="$2"
[[ "${count}" == ""         ]] && exit 1 # $count must be an integer
[[ "${count//[0-9]/}" != "" ]] && exit 2 # $count is not an integer
[[ "${count}" == "0"        ]] && exit 0 # nothing to do
[[ "${string}" == ""        ]] && exit 0 # nothing to do
#
# ========================================================================
# Find the highest 'power of 2' which, when calculated**, is <= count
#   ie. check ascending 'powers of 2'
((leqXpo=0))  # Exponent which makes 2** <= count 
((leqCnt=1))  # A count which is <= count
while ((count>=leqCnt)) ;do
  ((leqXpo+=1))
  ((leqCnt*=2))
done
((leqXpo-=1))
((leqCnt/=2))
#   
# ======================================================================================
# Output $string to 'tee's which are daisy-chained in groups of descending 'powers of 2'
todo=$count
for ((xpo=leqXpo ;xpo>0 ;xpo--)) ;do
  tchain="" 
  floor=$((2**xpo))
  if ((todo>=(2**xpo))) ; then
    for ((t=0 ;t<xpo ;t++)) ;do tchain="$tchain|tee -" ;done
    eval echo -n $e \"'$string'\" $tchain # >/dev/null
    ((todo-=floor))
  fi
done
if ((todo==1)) ;then 
  eval echo -n $e \"'$string'\" # >/dev/null
fi
#

Вот результаты испытаний некоторого времени.. Я перешел к 32 ГБ, потому что это о размере тестового файла, который я хотел создать (который является тем, что начало меня по этой проблеме),

NOTE: (2**30), etc. refers to the number of strings (to achieve a particular GB filesize)
-----
dd method (just for reference)                              real/user/sys
* 8GB                                                       =================================
    if=/dev/zero bs=1024 count=$(((1024**2)*8))         #   2m46.941s / 00m3.828s / 0m56.864s

tee method: fewer tests, because it didn't overflow, and the number-of-strings:time ratio is linear
tee method:              count        string                real/user/sys  
* 8GB                    ==========   ============          =================================
  tee(2**33)>stdout      $((2**33))   "x"               #   1m50.605s / 0m01.496s / 0m27.774s
  tee(2**30)>stdout  -e  $((2**30))   "xxx\txxx\n"      #   1m49.055s / 0m01.560s / 0m27.750s
* 32GB                                                     
  tee(2**35)>stdout  -e  $((2**35))   "x"               #   
  tee(2**32)>stdout  -e  $((2**32))   "xxx\txxx\n"      #   7m34.867s / 0m06.020s / 1m52.459s

python method: '.write'  uses 'file.write()' 
               '>stcout' uses 'sys.stdout.write()'. It handles \n in args (but I know very little python)
                            count   string                   real/user/sys
* 8GB                       =====   ===================      =================================
  python(2**33)a .write     2**33    "x"                 # OverflowError: repeated string is too long
  python(2**33)a >stdout    2**33    "x"                 # OverflowError: repeated string is too long
  python(2**30)b .write     2**30   '"xxxxxxxX" *2**0'   #   6m52.576s / 6m32.325s / 0m19.701s
  python(2**30)b >stdout    2**30   '"xxxxxxxX" *2**0'   #   8m11.374s / 7m49.101s / 0m19.573s
  python(2**30)c .write     2**20   '"xxxxxxxX" *2**10'  #   2m14.693s / 0m03.464s / 0m22.585s 
  python(2**30)c >stdout    2**20   '"xxxxxxxX" *2**10'  #   2m32.114s / 0m03.828s / 0m22.497s
  python(2**30)d .write     2**10   '"xxxxxxxX" *2**20'  #   2m16.495s / 0m00.024s / 0m12.029s
  python(2**30)d >stdout    2**10   '"xxxxxxxX" *2**20'  #   2m24.848s / 0m00.060s / 0m11.925s
  python(2**30)e .write     2**0    '"xxxxxxxX" *2**30'  # OverflowError: repeated string is too long
  python(2**30)e >stdout    2**0    '"xxxxxxxX" *2**30'  # OverflowError: repeated string is too long
* 32GB
  python(2**32)f.write      2**12   '"xxxxxxxX" *2**20'  #   7m58.608s / 0m00.160s / 0m48.703s
  python(2**32)f>stdout     2**12   '"xxxxxxxX" *2**20'  #   7m14.858s / 0m00.136s / 0m49.087s

perl method:
                           count   string                    real      / user       / sys
* 8GB                      =====   ===================       =================================
  perl(2**33)a .syswrite>  2**33    "a"        x 2**0    # Sloooooow! It would take 24 hours.   I extrapolated after 1 hour.   
  perl(2**33)a >stdout     2**33    "a"        x 2**0    #  31m46.405s / 31m13.925s /  0m22.745s
  perl(2**30)b .syswrite>  2**30    "aaaaaaaA" x 2**0    # 100m41.394s / 11m11.846s / 89m27.175s
  perl(2**30)b >stdout     2**30    "aaaaaaaA" x 2**0    #   4m15.553s /  3m54.615s /  0m19.949s
  perl(2**30)c .syswrite>  2**20    "aaaaaaaA" x 2**10   #   1m47.996s /  0m10.941s /  0m15.017s
  perl(2**30)c >stdout     2**20    "aaaaaaaA" x 2**10   #   1m47.608s /  0m12.237s /  0m23.761s
  perl(2**30)d .syswrite>  2**10    "aaaaaaaA" x 2**20   #   1m52.062s /  0m10.373s /  0m13.253s
  perl(2**30)d >stdout     2**10    "aaaaaaaA" x 2**20   #   1m48.499s /  0m13.361s /  0m22.197s
  perl(2**30)e .syswrite>  2**0     "aaaaaaaA" x 2**30   # Out of memory during string extend at -e line 1.   
  perl(2**30)e >stdout     2**0     "aaaaaaaA" x 2**30   # Out of memory during string extend at -e line 1.   
* 32GB
  perl(2**32)f .syswrite>  2**12    "aaaaaaaA" x 2**20   #   7m34.241s /  0m41.447s / 0m51.727s
  perl(2**32)f >stdout     2**12    "aaaaaaaA" x 2**20   #  10m58.444s /  0m53.771s / 1m28.498s
1
27.01.2020, 20:24
  • 1
    Для лучшей сопоставимости необходимо выполнить все тесты на/dev/shm, чтобы не вмешиваться в кэш жесткого диска. Конечно, только если у Вас есть достаточно RAM в Вашей машине. –  erik 06.06.2013, 12:02

Создайте маленький файл со строкой - здесь я использую "fussball", потому что это звучит немного как 'foobar', но 8 байтов длиной:

echo -n "fussball" >f3

Я теперь постоянно удваиваю размер произведенного файла и часы, какое повторение я нахожусь в ($i эха). Стартовое имя равняется 3, потому что 2^3=8, и 2^4 удвоение f3, который является f4 и так далее.

for i in {3..32}; do time cat f${i} f${i} > f$((i+1)) ; echo $i ; done
real    0m34.029s
user    0m0.016s
sys 0m3.868s
28

Я затем прерываю, если время выше 10 секунд и ниже одной минуты (2^28 байты). Затем я делаю подобный тест для dd, который заканчивается в том же размере файла:

for i in {1..16}; do time  dd if=/dev/zero of=g${i} bs=${i}M count=${i}  ; echo $i ; done
16+0 Datensätze ein
16+0 Datensätze aus
268435456 Bytes (268 MB) kopiert, 6,67487 s, 40,2 MB/s

real    0m6.683s
user    0m0.004s
sys 0m1.364s
16

Для файла размера 2^28 требуется приблизительно 35 секунд по сравнению с 7 секундами на 5-летнем ноутбуке с HDD IDE, не настроенная или специальная установка - случайная машина. Согласно моему вычислению. Dd-скорость 40MB/s о максимуме, который я испытал до сих пор. Является ли 1/5 той скорости к плохо для Вас, ваше дело решать. Но я должен выдать предупреждение: скорость cat a a > b- Тест не увеличивался линейно с размером. Иногда были те же времена для удвоенного размера, и иногда он брал 10* время для 2* размер.

И второй вызов сделал интенсивное использование кэша, таким образом, я должен был коснуться исходного файла, чтобы препятствовать тому, чтобы кошка обманула.:) И я предполагаю, что это зависит от памяти Вашей машины и размеров кэша, где пределы, где вещи ухудшаются, и где они работают хорошо.

0
27.01.2020, 20:24
  • 1
    В сущности это - то, что я сделал также.. (но по-другому)... Я проверю это позже (занятый теперь), и я "ответил" на вопрос со своей "мишенью" versoon... –  Peter.O 17.04.2011, 12:08
  • 2
    @user-unknown: я посмотрел на него снова.. Я думаю, что идея хороша (но я был бы, поскольку мы оба использовали двоичное удвоение :).. Это создает много файлов.. которые затем должны быть выборочно catd снова для получения финала требовал количества строк. например, 987654321... повторения Вашей строки... и поскольку Вы сказали, что она замедляет downa партию с большим числом повторения строк... Это работало в течение приблизительно 40 минут для создания файла на 32 ГБ, таким образом, я уничтожил его. (Я после файла на 35 ГБ..)... tee процесс, который я использовал, занимает 7-9 минут..., но меня все для двоичной идеи.. двоичные разделения и удвоения являются мощными инструментами –  Peter.O 17.04.2011, 13:54
[1181374] Для этого можно использовать [1181767]dd[1181768]! Сначала запишите строку в начало файла. Затем сделайте:

Примечание: если ваш $STRING_LENGTH маленький, вы можете сделать что-то вроде


(Этот пример работает только в том случае, если STRING_LENGTH имеет силу 2, а REPEAT_TIMES кратна 1024, но вы поняли)

  1. Если вы хотите использовать это, чтобы перезаписать файл (например cleanging) используйте [1181769]conv=notrunc
2
27.01.2020, 20:24

Пробовали ли вы использоватьyes(некоторые версии yesс высокой степенью оптимизации)? Также следите за трюком yes... | tr..., который, в свою очередь, может использоваться как вход для dd(, как упоминал @user23127 )! Изhttps://stackoverflow.com/a/10905109/2732969:

dd if=<(yes $'\xFF' | LANG=C tr -d "\n") of=file count=1024 bs=1024

(предполагая, что ваша оболочка bash -вроде ).

0
27.01.2020, 20:24

Чтобы все было быстро, будь проще:

yes "arbitrary string" | dd iflag=fullblock bs=1024 count=$((1024*386)) of=file
0
27.01.2020, 20:24

Теги

Похожие вопросы