dd memproduksi file acak 32 MB, bukannya 1 GB

50

Saya ingin menghasilkan file acak 1 GB, jadi saya menggunakan perintah berikut.

dd if=/dev/urandom of=output bs=1G count=1

Tetapi alih-alih setiap kali saya meluncurkan perintah ini saya mendapatkan file 32 MB:

<11:58:40>$ dd if=/dev/urandom of=output bs=1G count=1
0+1 records in
0+1 records out
33554431 bytes (34 MB, 32 MiB) copied, 0,288321 s, 116 MB/s

Apa yang salah?

SUNTING:

Berkat jawaban yang bagus dalam topik ini, saya datang dengan solusi yang bertuliskan 32 bongkahan 32 MB besar yang menghasilkan 1GB:

dd if=/dev/urandom of=output bs=32M count=32

Solusi lain diberikan yaitu membaca 1 GB langsung ke memori dan kemudian menulis ke disk. Solusi ini membutuhkan banyak memori sehingga tidak diutamakan:

dd if=/dev/urandom of=output bs=1G count=1 iflag=fullblock
Trismegistos
sumber
3
IMHO saya tidak berpikir ada banyak kasus penggunaan yang valid untuk ddsemua. Saya akan menggunakan head, catatau rsyncdi tempatnya hampir selalu. Dan pertanyaan Anda jika salah satu alasan mengapa alternatif biasanya lebih aman.
Bakuriu
@ Bakuriu - juga, jika Anda hanya ingin menghasilkan file yang penuh dengan nol (atau lebih tepatnya Anda tidak peduli dengan apa yang ada di dalamnya) gunakan truncate. Jauh lebih cepat.
Konrad Gajewski
@KonradGajewski FYI truncate mencoba membuat file yang jarang (jika itu penting)
Xen2050
5
@ Bakuriu headtidak dapat melakukan tugas ini tanpa -copsi yang tidak ada di POSIX . Saya tidak tahu versi catmana yang bisa menyelesaikan ini. rsyncadalah utilitas yang sama sekali tidak standar. Itu tidak ada di sini atau di sana; membaca halaman manualnya, saya juga tidak bisa mengatasi masalah ini.
Kaz
Secara teknis, /dev/urandomjuga tidak ada di POSIX ...
grawity

Jawaban:

92

bs, ukuran buffer, berarti ukuran panggilan read () tunggal yang dilakukan oleh dd.

(Misalnya, keduanya bs=1M count=1dan bs=1k count=1kakan menghasilkan file 1 MiB, tetapi versi pertama akan melakukannya dalam satu langkah, sedangkan yang kedua akan melakukannya dalam 1024 potongan kecil.)

File biasa dapat dibaca di hampir semua ukuran buffer (selama buffer itu sesuai dengan RAM), tetapi perangkat dan file "virtual" sering bekerja sangat dekat dengan panggilan individu dan memiliki pembatasan sewenang-wenang tentang berapa banyak data yang akan mereka hasilkan per baca () panggilan.

Sebab /dev/urandom, batas ini didefinisikan dalam urandom_read () di driver / char / random.c :

#define ENTROPY_SHIFT 3

static ssize_t
urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
    nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
    ...
}

Ini berarti bahwa setiap kali fungsi dipanggil, itu akan menjepit ukuran yang diminta ke 33554431 byte.

Secara default, tidak seperti kebanyakan alat lain, dd tidak akan mencoba lagi setelah menerima lebih sedikit data daripada yang diminta - Anda mendapatkan 32 MIB dan hanya itu. (Untuk membuatnya coba lagi secara otomatis, seperti dalam jawaban Kamil, Anda harus menentukan iflag=fullblock.)


Perhatikan juga bahwa "ukuran baca tunggal ()" berarti bahwa seluruh buffer harus muat dalam memori sekaligus, sehingga ukuran blok yang besar juga sesuai dengan penggunaan memori yang sangat besar oleh dd .

Dan itu semua tidak ada gunanya karena Anda biasanya tidak akan mendapatkan kinerja apa pun ketika pergi di atas ~ 16-32 blok MiB - syscalls bukan bagian yang lambat di sini, generator nomor acak adalah.

Jadi untuk kesederhanaan, gunakan saja head -c 1G /dev/urandom > output.

grawity
sumber
7
"... Anda biasanya tidak akan mendapatkan kinerja apa pun ketika pergi di atas ~ 16-32 blok MiB" - Dalam pengalaman saya, Anda cenderung tidak mendapatkan banyak, atau bahkan kehilangan kinerja di atas 64-128 kilo byte. Pada saat itu, Anda berada dalam pengurangan pengembalian biaya syscall, dan pertikaian cache mulai berperan.
marcelm
3
@marcelm Saya telah membantu arsitek sistem kinerja tinggi di mana kinerja IO akan meningkat ketika ukuran blok meningkat menjadi 1-2 MB, dan dalam beberapa kasus hingga 8 MB atau lebih. Per LUN. Dan ketika filesystem dibangun menggunakan beberapa LUN paralel, untuk mendapatkan kinerja terbaik berarti menggunakan beberapa utas untuk IO, masing-masing melakukan 1 MB + blok. Tingkat IO berkelanjutan lebih dari 1 GB / detik. Dan itu semua disk yang berputar, jadi saya bisa melihat array kinerja tinggi SSD menelan atau menghasilkan data lebih cepat dan lebih cepat ketika ukuran blok tumbuh menjadi 16 atau bahkan 32 MB blok. Dengan mudah. Mungkin lebih besar.
Andrew Henle
4
Saya akan secara eksplisit mencatat bahwa itu iflag=fullblockadalah ekstensi GNU ke utilitas POSIXdd . Karena pertanyaannya tidak menentukan Linux, saya pikir penggunaan ekstensi khusus Linux mungkin harus secara eksplisit dicatat agar beberapa pembaca di masa depan mencoba untuk memecahkan masalah serupa pada sistem non-Linux menjadi bingung.
Andrew Henle
6
@AndrewHenle Ah, menarik! Saya melakukan tes cepat dengan dddi mesin saya, dengan ukuran blok dari 1k ke 512M. Membaca dari Intel 750 SSD, kinerja optimal (sekitar 1300MiB / s) dicapai pada blok 2MiB, secara kasar mencocokkan hasil Anda. Ukuran blok yang lebih besar tidak membantu atau terhalang. Membaca dari /dev/zero, kinerja optimal (hampir 20GiB / s) berada di 64KiB dan 128KiB blok; blok yang lebih kecil dan lebih besar menurunkan kinerja, kira-kira cocok dengan komentar saya sebelumnya. Intinya: tolok ukur untuk situasi aktual Anda. Dan tentu saja, tidak satu pun dari kami yang melakukan benchmark /dev/random: P
marcelm
3
@ Xen2050 Saya melakukan beberapa tes lebih cepat, dan tampaknya ddlebih cepat. Sebuah strace cepat menunjukkan bahwa headmenggunakan 8KiB membaca, dan dua 4KiB menulis, yang menarik (GNU coreutils 8.26 pada Debian 9.6 / Linux 4.8). headkecepatan memang di suatu tempat antara dd bs=4kdan dd bs=8k. headkecepatan turun ~ 40% dibandingkan dd if=/dev/zero bs=64kdan turun ~ 25% dibandingkan dengan dd if=/dev/nvme0n1 bs=2M. Membaca dari /dev/zerotentu saja lebih terbatas pada CPU, tetapi untuk SSD I / O queing juga memainkan peran. Ini perbedaan yang lebih besar dari yang saya harapkan.
marcelm
21

dddapat membaca kurang dari ibs(catatan: bsmenentukan keduanya ibsdan obs), kecuali iflag=fullblockditentukan. 0+1 records inmenunjukkan bahwa 0blok penuh dan 1sebagian blok telah dibaca. Namun setiap blok penuh atau parsial meningkatkan penghitung.

Saya tidak tahu mekanisme pasti yang membuat ddmembaca blok yang kurang dari 1Gdalam kasus khusus ini. Saya kira semua blok dibaca ke memori sebelum ditulis, sehingga manajemen memori dapat mengganggu (tapi ini hanya dugaan). Sunting: jawaban serentak ini menjelaskan mekanisme yang membuat ddmembaca blok yang kurang dari 1Gdalam kasus khusus ini.

Lagi pula, saya tidak merekomendasikan sebesar itu bs. Saya akan menggunakan bs=1M count=1024. Yang paling penting adalah: tanpa iflag=fullblock setiap membaca upaya dapat membaca kurang dari ibs(kecuali ibs=1, saya pikir, ini meskipun cukup efisien).

Jadi, jika Anda perlu membaca sejumlah data, gunakan iflag=fullblock. Catatan iflagtidak diperlukan oleh POSIX, Anda ddmungkin tidak mendukungnya. Menurut jawaban ibs=1 ini mungkin satu-satunya cara POSIX untuk membaca jumlah byte yang tepat. Tentu saja jika Anda berubah ibsmaka Anda harus menghitung ulang count. Dalam kasus Anda menurunkan ibske 32Matau kurang mungkin akan memperbaiki masalah, bahkan tanpa iflag=fullblock.

Di Kubuntu saya, saya akan memperbaiki perintah Anda seperti ini:

dd if=/dev/urandom of=output bs=1M count=1024 iflag=fullblock
Kamil Maciorowski
sumber