Existuje rozdíl výkonu mezi přidělením paměti v době běhu a času kompilace v programovacím jazyce C?


Odpověď 1:

Ano, protože kompilátor a editor odkazů berou při rozložení výsledného spustitelného souboru v úvahu také statické přidělení paměti, protože požadované velikosti jsou předem známy a paměť takto přidělená zůstává rezervována po celou dobu trvání procesu.

Tímto způsobem se „staticky alokace paměti“ stává věcí „ponechání vhodných děr“ ve spustitelném souboru (všechny se zhroutily v sekci „data“ inicializované paměti a v „rss“ sekci neinicializované paměti), čímž se staly součástí procesu mapování spustitelného souboru v paměti při načtení programu bez výrazné režie za běhu.

Porovnejte to s dynamickým přidělováním z haldy za běhu, kde je alokátor (tj. Malloc (), calloc () atd.), Který musí sledovat aktuálně volné oblasti, aktuálně vyhrazené oblasti a pokaždé zjistit paměť se žádá o vhodnou volnou oblast při pokusu o zadržení externí fragmentace.

Zeptali jste se: Existuje rozdíl výkonu mezi přidělením paměti v době běhu a času kompilace v programovacím jazyce C?


Odpověď 2:

Ano, je zjevně rychlejší to udělat při kompilaci, ale záleží to. V podstatě to, co děláte s kompilací času, je předpočítání toho, co by se dělo za běhu.

To je v běžných systémech nízké úrovně, kde je malloc trochu zamračený, něco společného. Malloc plýtvá prostředky a cykly, takže pokud na to plánujete v době kompilace, můžete se této režii vyhnout.

Zevšeobecňuji se zde a někdy s tím zůstanete. Když se podíváte do mezioborového malloku, začnete chápat některá nebezpečí. Jak často provádíte volání operací s přidělením paměti, bude mít také vliv na režijní dopad.


Odpověď 3:

Ano, alokace času kompilace jsou založeny na blocích a nejsou spravovány. Runtime alokace jsou přidělovány z haldy a obvykle jsou dostatečně sledovány pro uvolnění později. (Říkám obecně, protože existuje mnoho různých algoritmů přidělování haldy, které jsou navrženy tak, aby upřednostňovaly různé vzory využití přidělení)

tak

čas kompilace:

statický znak bigstring [5000];

je to provedeno jednou, neexistuje skutečné sledování toho, co je přiděleno, je to jen část předběžně přiděleného datového bloku, když se spustí aplikace (myslím v podstatě endof stack před rámečkem stacku).

runtime:

char * pBigString = malloc (5000);

zahrnují místní haldu (halda C runtime), ačkoli jsou haldy optimalizované, mohou se roztříštit a v závislosti na implementaci zaberou malé množství času buď zdarma nebo malloc.

Nemůžete změnit velikost přiděleného času kompilace, zatímco runtime přidělení může mít libovolnou velikost. Bloky můžete recyklovat a nechat ukazatel na poslední, který jste přidělili, pokud máte obavy o výkon přidělení (za předpokladu, že jsou všechny stejné velikosti).


Odpověď 4:

Skutečný přístup do paměti je pro čtení a zápis naprosto stejný. Ale přidělení paměti za běhu vyžaduje čas. (a může selhat!).

Paměť je paměť. Je to rychlejší, než disk čte a zapisuje, USB přenosy atd. Hlavní paměť je ve srovnání s vyrovnávací pamětí CPU a také s grafickou pamětí na grafické kartě pomalá.

Kompilátoři C tedy vykonávají dobrou práci při optimalizaci kódu, který se spouští v mezipaměti, v závislosti na požadavcích a na hardwarové znalosti autora kódu. Zkompilovaný kód tedy běží velmi rychle a úložiště přidělené staticky se také načte do mezipaměti, pokud má správnou velikost.

Paměť přidělená za běhu (dynamická paměť, halda paměť) bude alokována ve stejné hlavní paměti jako kterákoli jiná, ale kompilátor ji předem nemůže velmi dobře optimalizovat. Může tedy být 50/50, zda bude vaše halda paměť trvat alokovat několik milisekund nebo několik set milisekund, a zda se vejde do mezipaměti CPU a bude na pěkné uklizené stránce paměti nebo se rozšíří na několik paměťových stránek.

Takže musíte průměrovat časy strávené ve funkci, která přiděluje paměť za běhu na velkém počtu běhů s různým načtením dat, abyste řekli, jak rychle bude funkce nebo jak pomalá může být, pokud věci nejsou v daném okamžiku optimální.

Moderní stolní počítače, servery, telefony atd. Fungují při velkém zatížení, protože programy zvyšují zdroje a čas CPU. Chcete-li, aby váš program oslovil operační systém pod velkým zatížením a vyžadoval přidělení paměťových služeb a také uvolnění paměti, bude to nějakou dobu trvat a je velmi obtížné odhadnout, jak dlouho, než budete moci začít psát Paměť.

Operační systémy mají spoustu triků, které v tom mohou zrychlit, kde mohou - kopírovat při zápisu, kde je požadována paměť a „přidělena“ programu, ale ve skutečnosti není dána, dokud se program nepokusí číst nebo zapisovat do to, virtuální paměť na diskových souborech, pro vymazání paměťových oblastí nečinných programů pro aktivní programy (odkládací soubory) atd.

To vše se obvykle děje pod úrovní, kde to programátor vidí nebo má kontrolu. Zdaleka nejpomalejší část paměti jsou I / O ze zařízení. Proto obvykle nejlepší zrychlení, které můžete mít, pokud máte úzká místa pro I / O u zařízení, je mapovat zařízení do paměti mapovaného SOUBORU s vyrovnávací pamětí a odložit I / O do samostatného vlákna.

Některé operační systémy dokonce poskytují souborový systém mapovaný na paměť, který můžete použít stejně jako běžný soubor nebo adresář! (Linux má adresář / var / run / shm ("shared mem"), ve kterém to můžete udělat - velmi rychle.)