Pertanyaan Apakah "Out Of Memory" Suatu Kesalahan yang Dapat Dipulihkan?


Saya telah memprogram waktu yang lama, dan program yang saya lihat, ketika kehabisan memori, mencoba untuk membersihkan dan keluar, yaitu gagal dengan anggun. Saya tidak ingat kapan terakhir kali saya melihat seseorang benar-benar mencoba untuk memulihkan dan terus beroperasi secara normal.

Begitu banyak proses bergantung pada kemampuan mengalokasikan memori, terutama dalam bahasa yang dikumpulkan, tampaknya kesalahan memori harus diklasifikasikan sebagai tidak dapat dipulihkan. (Kesalahan yang tidak dapat dipulihkan mencakup hal-hal seperti kelebihan tumpukan.)

Apa argumen yang memaksa untuk membuatnya menjadi kesalahan yang dapat dipulihkan?


75
2017-12-02 11:55


asal


Jawaban:


Itu benar-benar tergantung pada apa yang Anda bangun.

Ini tidak sepenuhnya tidak masuk akal untuk webserver gagal satu permintaan / respons pasangan tetapi kemudian terus berjalan untuk permintaan lebih lanjut. Anda harus yakin bahwa kegagalan tunggal tidak memiliki efek merugikan pada kondisi global, bagaimanapun - itu akan menjadi sedikit rumit. Mengingat bahwa kegagalan menyebabkan pengecualian di sebagian besar lingkungan terkelola (misalnya .NET dan Java), saya menduga bahwa jika pengecualian ditangani dalam "kode pengguna", itu dapat dipulihkan untuk permintaan di masa mendatang - mis. jika satu permintaan mencoba mengalokasikan memori 10GB dan gagal, itu seharusnya tidak membahayakan sistem lainnya. Jika sistem kehabisan memori ketika mencoba untuk menyerahkan permintaan ke kode pengguna, namun - hal semacam itu bisa lebih buruk.


35
2017-12-02 12:04



Di perpustakaan, Anda ingin menyalin file secara efisien. Ketika Anda melakukan itu, Anda biasanya akan menemukan bahwa menyalin menggunakan sejumlah kecil potongan besar jauh lebih efektif daripada menyalin banyak yang lebih kecil (misalnya, lebih cepat untuk menyalin file 15MB dengan menyalin 15 1MB potongan daripada menyalin 15'000 Potongan 1K).

Tetapi kode berfungsi dengan ukuran potongan apa pun. Jadi sementara itu mungkin lebih cepat dengan potongan 1MB, jika Anda mendesain untuk sistem di mana banyak file disalin, mungkin bijaksana untuk menangkap OutOfMemoryError dan mengurangi ukuran chunk sampai Anda berhasil.

Tempat lain adalah cache untuk Obyek yang disimpan dalam database. Anda ingin menyimpan sebanyak mungkin objek di cache, tetapi Anda tidak ingin mengganggu sisa aplikasi. Karena objek-objek ini dapat diciptakan kembali, ini adalah cara cerdas untuk menghemat memori untuk melampirkan cache ke luar dari pengendali memori untuk menjatuhkan entri hingga aplikasi lainnya memiliki cukup ruang untuk bernapas, lagi.

Terakhir, untuk manipulasi gambar, Anda ingin memuat sebanyak mungkin gambar ke dalam memori. Sekali lagi, OOM-handler memungkinkan Anda untuk mengimplementasikannya tanpa mengetahui terlebih dahulu berapa banyak memori yang akan diberikan oleh pengguna atau OS Anda.

[EDIT] Perhatikan bahwa saya bekerja berdasarkan asumsi di sini bahwa Anda telah memberikan aplikasi jumlah memori yang tetap dan jumlah ini lebih kecil dari total memori yang tersedia, tidak termasuk ruang swap. Jika Anda dapat mengalokasikan begitu banyak memori yang sebagian harus ditukar, beberapa komentar saya tidak masuk akal lagi.


17
2017-12-02 12:16



Pengguna MATLAB kehabisan memori sepanjang waktu ketika melakukan aritmatika dengan array besar. Sebagai contoh jika variabel x cocok dalam memori dan mereka menjalankan "x + 1" maka MATLAB mengalokasikan ruang untuk hasil dan kemudian mengisinya. Jika alokasi gagal MATLAB kesalahan dan pengguna dapat mencoba sesuatu yang lain. Akan menjadi bencana jika MATLAB keluar setiap kali kasus penggunaan ini muncul.


9
2017-12-02 16:08



OOM harus dapat dipulihkan karena shutdown bukan satu-satunya strategi untuk memulihkan dari OOM.

Sebenarnya ada solusi standar yang cukup untuk masalah OOM di tingkat aplikasi. Sebagai bagian dari desain aplikasi Anda menentukan jumlah minimum yang aman dari memori yang diperlukan untuk pulih dari kondisi kehabisan memori. (Misalnya, memori yang diperlukan untuk menyimpan dokumen secara otomatis, memunculkan dialog peringatan, data log shutdown).

Pada awal aplikasi Anda atau di awal blok kritis, pra-alokasikan jumlah memori tersebut. Jika Anda mendeteksi keluar dari kondisi memori, lepaskan memori penjaga Anda dan lakukan pemulihan. Strategi ini masih bisa gagal tetapi secara keseluruhan memberikan bang besar untuk uang.

Perhatikan bahwa aplikasi tidak perlu ditutup. Ini dapat menampilkan dialog modal sampai kondisi OOM telah diselesaikan.

Saya tidak 100% yakin tapi saya cukup yakin 'Kode Lengkap'(Pembacaan yang diperlukan untuk setiap insinyur perangkat lunak yang terhormat) mencakup ini.

P.S. Anda dapat memperluas kerangka aplikasi Anda untuk membantu dengan strategi ini tetapi tolong jangan menerapkan kebijakan seperti itu di perpustakaan (perpustakaan yang baik tidak membuat keputusan global tanpa persetujuan aplikasi)


7
2018-01-03 22:37



Saya pikir itu seperti banyak hal, ini adalah analisis biaya / manfaat. Kamu bisa program dalam upaya pemulihan dari kegagalan malloc () - meskipun mungkin sulit (pawang Anda sebaiknya tidak jatuh karena kekurangan memori yang sama yang dimaksudkan untuk ditangani).

Anda telah mencatat bahwa kasus yang paling umum adalah membersihkan dan gagal dengan anggun. Dalam hal ini sudah diputuskan bahwa biaya aborsi dengan anggun lebih rendah dari kombinasi biaya pengembangan dan biaya kinerja dalam pemulihan.

Saya yakin Anda dapat memikirkan contoh-contoh situasi Anda sendiri ketika mengakhiri program adalah opsi yang sangat mahal (mesin pendukung kehidupan, kontrol pesawat ruang angkasa, perhitungan keuangan jangka panjang dan waktu-kritis, dll.) - meskipun garis pertahanan pertama adalah tentu saja untuk memastikan bahwa program memiliki penggunaan memori yang dapat diprediksi dan lingkungan dapat menyediakan itu.


5
2017-12-02 12:08



Saya sedang bekerja pada sistem yang mengalokasikan memori untuk IO cache untuk meningkatkan kinerja. Kemudian, ketika mendeteksi OOM, ia mengambil sebagian kembali, sehingga logika bisnis dapat dilanjutkan, meskipun itu berarti cache IO yang lebih sedikit dan kinerja penulisan sedikit lebih rendah.

Saya juga bekerja dengan aplikasi Java tertanam yang berusaha untuk mengelola OOM dengan memaksa pengumpulan sampah, opsional melepaskan beberapa objek non-kritis, seperti data yang diambil sebelumnya atau cache.

Masalah utama dengan penanganan OOM adalah:

1) dapat mencoba kembali di tempat di mana terjadi atau dapat memutar kembali dan mencoba kembali dari titik yang lebih tinggi. Kebanyakan program kontemporer terlalu bergantung pada bahasa untuk dibuang dan tidak benar-benar mengelola di mana mereka berakhir dan bagaimana untuk mencoba kembali operasi tersebut. Biasanya konteks operasi akan hilang, jika tidak dirancang untuk dilestarikan

2) dapat benar-benar melepaskan beberapa memori. Ini berarti semacam manajer sumber daya yang mengetahui objek apa yang penting dan apa yang tidak, dan sistem dapat meminta ulang objek yang dilepaskan kapan dan jika kemudian menjadi kritis

Masalah penting lainnya adalah dapat memutar kembali tanpa memicu lagi situasi OOM lain. Ini adalah sesuatu yang sulit dikontrol dalam bahasa tingkat yang lebih tinggi.

Selain itu, OS yang mendasari harus berperilaku secara prediktif berkaitan dengan OOM. Linux, misalnya, tidak akan, jika overkomit memori diaktifkan. Banyak sistem swap-enabled akan mati lebih cepat daripada melaporkan OOM ke aplikasi yang melanggar.

Dan, ada kasus ketika bukan proses Anda yang menciptakan situasi, sehingga melepaskan memori tidak membantu jika proses yang menyinggung terus bocor.

Karena semua ini, seringkali sistem besar dan tertanam yang menggunakan teknik ini, karena mereka memiliki kendali atas OS dan memori untuk memungkinkan mereka, dan disiplin / motivasi untuk menerapkannya.


5
2017-12-02 12:18



Ini dapat dipulihkan hanya jika Anda menangkapnya dan menanganinya dengan benar.

Dalam kasus yang sama, misalnya, permintaan mencoba mengalokasikan banyak memori. Ini cukup mudah ditebak dan Anda bisa mengatasinya dengan sangat baik.

Namun, dalam banyak kasus dalam aplikasi multi-thread, OOE juga dapat terjadi pada latar belakang (termasuk yang dibuat oleh sistem / pustaka pihak ketiga). Ini hampir tidak dapat diprediksi dan Anda mungkin tidak dapat memulihkan keadaan semua utas Anda.


4
2017-12-02 12:38



Tidak. Kesalahan memori dari GC seharusnya tidak dapat dipulihkan secara umum di dalam rangkaian saat ini. (Kreasi atau penghentian thread yang dapat dipulihkan (pengguna atau kernel) harus didukung sekalipun)

Mengenai contoh counter: Saat ini saya sedang mengerjakan proyek bahasa pemrograman D yang menggunakan platform CUDA NVIDIA untuk komputasi GPU. Alih-alih mengelola memori GPU secara manual, saya telah membuat objek proxy untuk memanfaatkan D's GC. Jadi ketika GPU mengembalikan kesalahan memori, saya menjalankan pengumpulan penuh dan hanya meningkatkan pengecualian jika gagal untuk kedua kalinya. Tapi, ini bukan benar-benar contoh dari pemulihan memori, itu lebih merupakan salah satu integrasi GC. Contoh lain dari pemulihan (cache, daftar-bebas, tumpukan / hash tanpa penyusutan otomatis, dll) adalah semua struktur yang memiliki metode pengumpulan / pemadatan memori sendiri yang terpisah dari GC dan cenderung tidak lokal untuk mengalokasikan fungsi. Jadi orang-orang mungkin menerapkan sesuatu seperti berikut:

T new2(T)( lazy T old_new ) {
    T obj;
    try{
        obj = old_new;
    }catch(OutOfMemoryException oome) {
        foreach(compact; Global_List_Of_Delegates_From_Compatible_Objects)
            compact();
        obj = old_new;
    }
    return obj;
}

Yang merupakan argumen yang layak untuk menambahkan dukungan untuk mendaftarkan / tidak mendaftarkan diri mengumpulkan / memadatkan objek ke pemulung pada umumnya.


3
2017-12-02 15:26



Dalam kasus umum, itu tidak dapat dipulihkan.

Namun, jika sistem Anda menyertakan beberapa bentuk caching dinamis, pengendali out-of-memory sering dapat membuang elemen tertua di cache (atau bahkan seluruh cache).

Tentu saja, Anda harus memastikan bahwa proses "dumping" tidak memerlukan alokasi memori baru :) Juga, bisa rumit untuk memulihkan alokasi spesifik yang gagal, kecuali Anda dapat menyambungkan kode dumping cache langsung di pengalokasi tingkat, sehingga kegagalan tidak disebarkan ke penelepon.


1
2017-12-02 12:03