A ka ndonjë ndryshim mes performancës midis alokimit të kujtesës në kohën e funksionimit dhe kohës së përpilimit në gjuhën e programimit C?


përgjigje 1:

Po, pasi që përpiluesi dhe lidhësi gjithashtu marrin parasysh ndarjet statike të kujtesës kur vendosni ekzekutuesin që rezulton, pasi madhësitë e kërkuara njihen të gjitha paraprakisht dhe memorja e alokuar në këtë mënyrë mbetet e rezervuar për të gjithë kohëzgjatjen e procesit.

Në këtë mënyrë, ndarja statike e kujtesës për një gjë që konsiston në lënien e boshllëqeve të përshtatshme në ekzekutues (të cilat janë grupuar të gjithë së bashku në një seksion të të dhënave të memorjes së inicializuar dhe në një seksion RSS të kujtesës së paautorizuar) bëhet pjesë Procesi i caktimit të skedarit të ekzekutueshëm në memorje kur ngarkoni programin pa asnjë kapital të konsiderueshëm në kohën e ekzekutimit.

Krahasoni këtë me alokimin dinamik nga grumbulli në kohën e ekzekutimit, ku ekziston një alokator (d.m.th. malloc (), calloc () etj) që duhet të zbulojë zonat aktualisht të lira, zonat e rezervuara aktualisht dhe çdo herë disa memorie Kërkohet hapësirë ​​e përshtatshme e lirë ndërsa përpiqeni të ndaloni copëtimin e jashtëm.

Ju keni pyetur: A ka ndonjë ndryshim në performancën midis alokimit të RAM në kohën e ekzekutimit dhe kohës së përpilimit në gjuhën e programimit C?


përgjigje 2:

Po, është padyshim më e shpejtë ta bësh këtë në kohën e përpilimit, por kjo varet. Në thelb, koha e përpilimit përdoret për të llogaritur atë që do të ndodhte në kohën e funksionimit.

Kjo është e zakonshme në sistemet e nivelit të ulët, ku Malloc është disi i inatosur. Malloc po harxhon burime dhe cikle. Nëse e planifikoni këtë në kohën e përpilimit, mund ta shmangni këtë planifikim.

Unë përgjithësoj këtu, dhe ndonjëherë ju rrinë me të. Nëse shikoni ndërthurjen e malloc, do të filloni të kuptoni disa nga rreziqet. Numri i herë kur bëni thirrje për ndarjen e kujtesës gjithashtu ndikon në pjesën e sipërme.


përgjigje 3:

Po, hartat e kohës së përpilimit janë të bazuara në bllok dhe nuk menaxhohen. Ndarjet për kohën e caktuar caktohen nga një grumbull dhe në përgjithësi ndiqen në mënyrë adekuate për lëshimin e mëvonshëm. (Unë zakonisht them sepse ekzistojnë shumë algoritme të ndryshme të alokimit të grumbullit që preferojnë modele të ndryshme të përdorimit për alokim.)

si kjo

Koha e përpilimit:

varg statik [5000];

është bërë një herë, nuk ka një gjurmim të vërtetë të asaj që është alokuar, ai është vetëm një pjesë e bllokut të të dhënave të paracaktuara kur fillon një aplikacion (mendoj se në thelb rafte para kornizës së pirgut).

Duration:

char * pBigString = malloc (5000);

Përfshini grumbullimin lokal (grumbullimi i afatit C). Edhe pse grumbullohet optimizuar, ato mund të jenë të fragmentuara dhe të marrin pak kohë në varësi të zbatimit.

Ju nuk mund të ndryshoni madhësinë e një detyre të përpilimit në kohë, ndërsa detyrat në kohën e funksionimit mund të jenë me çdo madhësi. Ju mund të ricikloni blloqet tuaja dhe të mbani një tregues në atë të fundit të caktuar nëse jeni të shqetësuar për punën e caktimit (me kusht që të gjitha ato janë me të njëjtën madhësi).


përgjigje 4:

Qasja e memorjes aktuale është e njëjtë për lexime dhe shkrime. Alokimi i kujtesës në kohën e funksionimit kërkon ca kohë. (dhe mund të dështojë!)

Kujtesa është kujtesë. Shtë shumë më shpejt sesa leximi dhe shkrimi i bartësve të të dhënave, transferimeve USB etj. Kujtesa kryesore është shumë e ngadaltë në krahasim me cache e CPU-së dhe memorie video në kartën grafike.

Kështu që përpiluesit C optimizojnë kodin që ekzekutohet në cache. Kjo varet nga kërkesat dhe njohuritë e harduerit të krijuesit të kodit. Prandaj, kodi i përpiluar funksionon shumë shpejt dhe memorja e caktuar statike gjithashtu ngarkohet në cache nëse është e madhësisë së saktë.

Kujtesa e alokuar në kohën e funksionimit (memorje dinamike, memorie grumbulluese) shpërndahet në të njëjtën memorje kryesore si çdo tjetër, por nuk mund të optimizohet shumë më parë nga përpiluesi. Kështu që mund të jetë 50/50 nëse memorja juaj grumbullohet disa milisekonda ose disa qindra milisekonda dhe nëse gjithçka përshtatet në cache të CPU-së dhe është në një faqe të zoti ose në disa faqe.

Kështu që ju duhet të mesatarizoni kohën e kaluar në një funksion që rezervon kujtesën në kohën e funksionimit për një numër të madh ekzekutimesh me ngarkesa të ndryshme të të dhënave për të përcaktuar se sa i shpejtë do të jetë funksioni ose sa i ngadalshëm mund të jetë nëse gjërat nuk funksionojnë në atë pikë janë optimale.

Desktop moderne, serverat, telefonat etj përdoren shumë sepse programet marrin burime dhe kohë të CPU. Duhet ca kohë që programi juaj të kontaktojë sistemin operativ dhe të kërkojë ndarje të kujtesës nën ngarkesë të rëndë, dhe është jashtëzakonisht e vështirë të vlerësohet saktësisht se sa kohë do të zgjasë para se të filloni të shkruani memorie.

Sistemet operative mund të përdorin një numër mashtrimesh për ta shpejtuar këtë. Ju mund të kopjoni ndërsa shkruani, kërkoni dhe "jepni" kujtesën në program, por vetëm kur programi përpiqet ta lexojë ose shkruajë atë. Isshtë memorja virtuale në skedarët e diskut për të fshirë zonat e kujtesës të programeve joaktive, që mund të përdoren nga programet aktive (skedarë shkëmbimi) etj.

Kjo zakonisht ndodh nën nivelin në të cilin programuesi e sheh atë ose është në kontroll. Deri më tani, pjesa më e ngadaltë e kujtesës është pajisja I / O. Në mënyrë tipike, shpejtësia më e mirë që mund të merrni me shishet e I / O të pajisjes është të hidhni pajisjen në një FILE të hartuar nga memorja me një tampon dhe të ndërroni I / O në një fije të veçantë.

Disa sisteme operative madje ju ofrojnë një sistem skedar të caktuar për memorje që mund ta përdorni si një skedar normal ose direktori! (Linux ka drejtorinë / var / run / shm ("memorja e përbashkët") ku mund ta bëni vetëm atë - shumë shpejt.)