Saya memiliki server web yang akan membaca file biner besar (beberapa megabita) ke dalam byte array. Server dapat membaca beberapa file secara bersamaan (permintaan halaman berbeda), jadi saya mencari cara yang paling optimal untuk melakukan ini tanpa membebani CPU terlalu banyak. Apakah kode di bawah ini cukup baik?
public byte[] FileToByteArray(string fileName)
{
byte[] buff = null;
FileStream fs = new FileStream(fileName,
FileMode.Open,
FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
long numBytes = new FileInfo(fileName).Length;
buff = br.ReadBytes((int) numBytes);
return buff;
}
c#
.net
bytearray
binary-data
Tony_Henrich
sumber
sumber
byte[] buff = File.ReadAllBytes(fileName)
.Jawaban:
Cukup ganti semuanya dengan:
Namun, jika Anda khawatir tentang konsumsi memori, Anda tidak harus membaca keseluruhan file sekaligus. Anda harus melakukannya dalam potongan.
sumber
Saya mungkin berpendapat bahwa jawaban di sini umumnya adalah "jangan". Kecuali Anda benar-benar membutuhkan semua data sekaligus, pertimbangkan untuk menggunakan
Stream
API berbasis (atau varian pembaca / iterator). Itu sangat penting ketika Anda memiliki beberapa operasi paralel (seperti yang disarankan oleh pertanyaan) untuk meminimalkan beban sistem dan memaksimalkan throughput.Misalnya, jika Anda mengalirkan data ke penelepon:
sumber
byte[]
karena suatu alasan, saya sarankan menghindari menggunakan stream atau apa pun dan hanya menggunakan sistem yang disediakan API.File.ReadAllBytes
.Saya akan memikirkan ini:
sumber
Kode Anda dapat diperhitungkan untuk ini (sebagai pengganti File.ReadAllBytes):
Perhatikan Integer.MaxValue - batasan ukuran file yang ditempatkan oleh metode Baca. Dengan kata lain Anda hanya dapat membaca potongan 2GB sekaligus.
Perhatikan juga bahwa argumen terakhir untuk FileStream adalah ukuran buffer.
Saya juga menyarankan membaca tentang FileStream dan BufferedStream .
Seperti biasa, contoh program sederhana untuk profil yang tercepat akan sangat bermanfaat.
Perangkat keras Anda juga akan memiliki efek besar pada kinerja. Apakah Anda menggunakan hard disk drive berbasis server dengan cache besar dan kartu RAID dengan cache memori terpasang? Atau apakah Anda menggunakan drive standar yang terhubung ke port IDE?
sumber
var binaryReader = new BinaryReader(fs); fileData = binaryReader.ReadBytes((int)fs.Length);
dalamusing
pernyataan itu. Tapi itu efektif seperti apa yang OP lakukan, hanya saya memotong baris kode dengan castingfs.Length
untukint
bukannya mendapatkanlong
nilaiFileInfo
panjang dan mengkonversi itu.Bergantung pada frekuensi operasi, ukuran file, dan jumlah file yang Anda lihat, ada masalah kinerja lain yang perlu dipertimbangkan. Satu hal yang perlu diingat, adalah bahwa masing-masing byte array Anda akan dirilis pada belas kasihan pengumpul sampah. Jika Anda tidak melakukan caching data apa pun, Anda bisa menghasilkan banyak sampah dan kehilangan sebagian besar kinerja Anda menjadi % Waktu dalam GC. Jika potongan lebih besar dari 85K, Anda akan mengalokasikan ke Large Object Heap (LOH) yang akan membutuhkan koleksi semua generasi untuk dibebaskan (ini sangat mahal, dan pada server akan menghentikan semua eksekusi saat sedang berlangsung ). Selain itu, jika Anda memiliki banyak objek pada LOH, Anda dapat berakhir dengan fragmentasi LOH (LOH tidak pernah dipadatkan) yang mengarah pada kinerja yang buruk dan keluar dari memori. Anda dapat mendaur ulang proses setelah mencapai titik tertentu, tetapi saya tidak tahu apakah itu praktik terbaik.
Intinya adalah, Anda harus mempertimbangkan siklus hidup lengkap aplikasi Anda sebelum hanya membaca semua byte ke dalam memori secepat mungkin atau Anda mungkin memperdagangkan kinerja jangka pendek untuk kinerja keseluruhan.
sumber
garbage collector
,chunks
, kinerja, acara counter , ...Saya katakan
BinaryReader
baik-baik saja, tetapi bisa dire-refored untuk ini, alih-alih semua baris kode untuk mendapatkan panjang buffer:Seharusnya lebih baik daripada menggunakan
.ReadAllBytes()
, karena saya melihat di komentar pada respon teratas yang mencakup.ReadAllBytes()
bahwa salah satu komentator memiliki masalah dengan file> 600 MB, karena aBinaryReader
dimaksudkan untuk hal semacam ini. Juga, memasukkannya ke dalamusing
pernyataan memastikanFileStream
danBinaryReader
ditutup serta dibuang.sumber
new
tidak diperlukan di sana. Dihapus.Dalam hal 'file besar' dimaksudkan di luar batas 4GB, maka logika kode tertulis berikut sesuai. Masalah utama yang perlu diperhatikan adalah tipe data PANJANG yang digunakan dengan metode SEEK. Sebagai PANJANG mampu menunjukkan 2 ^ 32 batas data. Dalam contoh ini, kode memproses pertama memproses file besar dalam potongan 1GB, setelah seluruh potongan 1GB besar diproses, byte sisa (<1GB) diproses. Saya menggunakan kode ini dengan menghitung CRC file di luar ukuran 4GB. (menggunakan https://crc32c.machinezoo.com/ untuk perhitungan crc32c dalam contoh ini)
sumber
Gunakan kelas BufferedStream di C # untuk meningkatkan kinerja. Buffer adalah blok byte dalam memori yang digunakan untuk menyimpan data, sehingga mengurangi jumlah panggilan ke sistem operasi. Buffer meningkatkan kinerja membaca dan menulis.
Lihat berikut ini untuk contoh kode dan penjelasan tambahan: http://msdn.microsoft.com/en-us/library/system.io.bufferedstream.aspx
sumber
BufferedStream
ketika Anda membaca semuanya sekaligus?Gunakan ini:
sumber
Tinjauan Umum: jika gambar Anda ditambahkan sebagai action = sumber daya yang disematkan maka gunakan GetExecutingAssembly untuk mengambil sumber daya jpg ke dalam aliran kemudian baca data biner dalam aliran ke dalam array byte
sumber
Saya akan merekomendasikan mencoba
Response.TransferFile()
metode ituResponse.Flush()
danResponse.End()
untuk melayani file-file besar Anda.sumber
Jika Anda berurusan dengan file di atas 2 GB, Anda akan menemukan bahwa metode di atas gagal.
Jauh lebih mudah untuk menyerahkan streaming ke MD5 dan membiarkannya memotong file Anda:
sumber