Apakah ada perbedaan kinerja antara mengalokasikan memori dalam waktu berjalan vs waktu kompilasi dalam bahasa pemrograman C?


Jawaban 1:

Ya, karena kompilator dan editor tautan juga mempertimbangkan alokasi memori statis ketika meletakkan hasil yang dapat dieksekusi, karena ukuran yang diminta semuanya diketahui sebelumnya dan memori yang dialokasikan dengan cara itu tetap disediakan untuk semua durasi proses.

Dengan cara itu, "mengalokasikan memori secara statis" menjadi masalah "meninggalkan lubang yang cocok" di executable (semua runtuh di bagian "data" dari memori yang diinisialisasi dan di bagian "rss" dari memori yang tidak diinisialisasi), sehingga menjadi bagian dari proses memetakan executable dalam memori pada beban program tanpa overhead yang terlihat saat runtime.

Bandingkan dengan alokasi dinamis dari heap saat runtime, di mana ada pengalokasi (yaitu malloc (), calloc (), dll.) Yang harus melacak area yang saat ini gratis, area yang saat ini disediakan, dan untuk mengetahui setiap kali beberapa memori diminta area bebas yang cocok saat mencoba menahan fragmentasi eksternal.

Anda bertanya: Apakah ada perbedaan kinerja antara mengalokasikan memori dalam waktu berjalan vs waktu kompilasi dalam bahasa pemrograman C?


Jawaban 2:

Ya itu jelas lebih cepat untuk melakukannya pada waktu kompilasi tetapi ini tergantung. Pada dasarnya apa yang Anda lakukan dengan waktu kompilasi adalah precomputing apa yang akan dilakukan saat runtime.

Ini adalah jenis umum dalam sistem tingkat rendah di mana malloc agak disukai. Malloc menyia-nyiakan sumber daya dan siklus jadi jika Anda merencanakan ini pada waktu kompilasi Anda dapat menghindari overhead ini.

Saya menggeneralisasi di sini, dan kadang-kadang Anda terjebak dengan itu. Jika Anda melihat ke dalam interworking's dari malloc Anda akan mulai memahami beberapa bahaya. Seberapa sering Anda melakukan panggilan operasi alokasi memori juga akan mempengaruhi dampak overhead.


Jawaban 3:

Ya, kompilasi alokasi waktu didasarkan pada blok, dan tidak dikelola. Alokasi runtime dialokasikan dari tumpukan dan umumnya dilacak cukup untuk membebaskan nanti. (Saya katakan secara umum, karena ada banyak algoritma alokasi tumpukan berbeda yang dirancang untuk mendukung pola penggunaan alokasi yang berbeda)

begitu

waktu kompilasi:

bigstring char statis [5000];

itu dilakukan sekali, tidak ada pelacakan nyata dari apa yang dialokasikan, itu hanya bagian dari blok data yang dialokasikan sebelumnya ketika aplikasi dimulai (pada dasarnya endof stack sebelum bingkai stack saya pikir).

runtime:

char * pBigString = malloc (5000);

melibatkan tumpukan lokal (tumpukan runtime C), meskipun tumpukan dioptimalkan, mereka dapat menjadi terfragmentasi, dan mengambil sedikit waktu baik pada gratis atau malloc tergantung pada implementasinya.

Anda tidak dapat mengubah ukuran alokasi waktu kompilasi, sedangkan alokasi runtime dapat berupa ukuran apa pun yang Anda suka. Anda dapat mendaur ulang blok Anda dan menyimpan pointer ke yang terakhir yang Anda alokasikan jika Anda khawatir tentang kinerja alokasi (dengan asumsi mereka semua berukuran sama).


Jawaban 4:

Akses memori yang sebenarnya persis sama untuk membaca dan menulis. Tetapi alokasi memori pada saat dijalankan membutuhkan waktu. (dan bisa gagal!).

Memori adalah memori. Ini jauh lebih cepat daripada membaca dan menulis disk, transfer USB, dll. Memori utama secara glacially lambat dibandingkan dengan memori cache CPU, dan juga untuk memori video dalam kartu video.

Jadi kompiler C melakukan pekerjaan yang baik untuk mengoptimalkan kode untuk berjalan di cache, tergantung pada persyaratan, dan pengetahuan perangkat keras dari penulis kode. Jadi kode yang dikompilasi berjalan sangat cepat, dan penyimpanan yang dialokasikan secara statis akan dimuat ke dalam cache juga jika berukuran tepat.

Memori yang dialokasikan pada waktu berjalan (memori dinamis, memori tumpukan) akan dialokasikan dalam memori utama yang sama seperti yang lain, tetapi tidak dapat dioptimalkan oleh kompiler sebelumnya dengan sangat baik. Jadi mungkin 50/50 apakah memori tumpukan Anda akan mengambil beberapa milidetik atau beberapa ratus milidetik untuk mengalokasikan, dan apakah itu akan cocok dengan semua dalam cache CPU, dan berada di halaman memori rapi bagus atau tersebar di beberapa halaman memori.

Jadi, Anda harus rata-rata waktu yang dihabiskan dalam suatu fungsi yang mengalokasikan memori pada waktu menjalankan lebih dari sejumlah besar berjalan dengan berbagai beban data untuk mengetahui seberapa cepat fungsi akan atau seberapa lambat dapat jika hal-hal tidak optimal pada saat itu.

Desktop modern, server, telepon, dll, beroperasi di bawah beban berat, karena program-program menghabiskan sumber daya dan waktu CPU. Agar program Anda menjangkau Sistem Pengoperasian di bawah beban berat dan meminta alokasi layanan memori, dan juga melepaskan memori, akan membutuhkan waktu, dan sangat sulit untuk mengukur dengan tepat berapa lama, sebelum Anda dapat mulai menulis itu. Penyimpanan.

Sistem operasi memiliki banyak trik untuk digunakan dalam hal ini untuk mempercepat ini di mana mereka dapat— menyalin pada tulis, di mana memori diminta dan "diberikan" untuk program tetapi tidak benar-benar diberikan sama sekali sampai program mencoba membaca atau menulis ke itu, memori virtual pada file disk, untuk menghapus wilayah memori program yang tidak aktif untuk digunakan (bertukar file), dll.

Ini semua dilakukan biasanya di bawah tingkat di mana programmer melihatnya atau memiliki kontrol. Sejauh ini, bagian memori yang paling lambat adalah I / O dari perangkat. Jadi biasanya speedup terbaik yang bisa Anda miliki jika Anda mengalami kemacetan I / O dengan perangkat adalah memetakan perangkat ke FILE yang dipetakan dengan buffer dan melepas muatan I / O ke utas terpisah.

Beberapa OS bahkan memberi Anda filesystem yang dipetakan dengan memori yang dapat Anda gunakan seperti file atau direktori biasa! (Linux memiliki direktori / var / run / shm ("shared mem") di mana Anda dapat melakukan hal itu - sangat cepat.)