Существует несколько способов выполнить это. Самое легкое должно, вероятно, настроить то, что известно как демилитаризованная зона. Больше безопасного пути, однако, находится на Вашем маршрутизаторе для установки статического маршрута на порте 22 к IP сервера.
Ресурсы:
$ 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 x
s) с чем Вам нравится.
Можно оптимизировать это далее при помощи большей строки в каждом цикле и обхода нормального стандарта, буферизующего.
$ 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
Обычно ожидается, что оболочки медленные при обработке больших частей данных. Для большинства сценариев Вы знаете заранее, какие биты данных, вероятно, будут маленькими и какие биты данных, вероятно, будут большими.
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 так или иначе.
dd
, и, кажется, довольно равнодушен к размеру строки... (Я попытаюсь отправить его когда-то завтра, после того как я получаю его аккуратный :)...
– Peter.O
16.04.2011, 22:37
Версия 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 в моей системе.
Я наконец надел свою идею, как сделать эту работу... Это использует 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
Создайте маленький файл со строкой - здесь я использую "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* размер.
И второй вызов сделал интенсивное использование кэша, таким образом, я должен был коснуться исходного файла, чтобы препятствовать тому, чтобы кошка обманула.:) И я предполагаю, что это зависит от памяти Вашей машины и размеров кэша, где пределы, где вещи ухудшаются, и где они работают хорошо.
cat
d снова для получения финала требовал количества строк. например, 987654321... повторения Вашей строки... и поскольку Вы сказали, что она замедляет downa партию с большим числом повторения строк... Это работало в течение приблизительно 40 минут для создания файла на 32 ГБ, таким образом, я уничтожил его. (Я после файла на 35 ГБ..)... tee
процесс, который я использовал, занимает 7-9 минут..., но меня все для двоичной идеи.. двоичные разделения и удвоения являются мощными инструментами
– Peter.O
17.04.2011, 13:54
Примечание: если ваш $STRING_LENGTH маленький, вы можете сделать что-то вроде
(Этот пример работает только в том случае, если STRING_LENGTH имеет силу 2, а REPEAT_TIMES кратна 1024, но вы поняли)
Пробовали ли вы использовать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 -вроде ).
Чтобы все было быстро, будь проще:
yes "arbitrary string" | dd iflag=fullblock bs=1024 count=$((1024*386)) of=file
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