Onko calloc () todella hitaampaa kuin malloc (), koska se alustaa muistin nollaan ja alustus vie aikaa, kun taas malloc () ei? Onko suorituskykyero näiden 2 toiminnon välillä merkittävä?


Vastaus 1:

calloc () ei voi koskaan olla nopeampi kuin malloc (), koska calloc () toteutetaan.

Kuten mainitsit, calloc asettaa muistin nollaan, mikä voi viedä aikaa. Mutta se todella riippuu käyttöjärjestelmästäsi. Jos käyttöjärjestelmäsi voi tarjota callocille nolla sivua, niin sitä ei tarvitse nollata. Mutta enemmän kuin, kallokki koskettaa muistia. Käyttöjärjestelmän on itse asiassa löydettävä sopiva sijainti ennen kuin calloc-puhelu palaa.

malloc saattaa palata nopeammin Linuxissa, koska mikään muisti ei tue sitä, ennen kuin käytät muistia. Linux tekee jotain, jota kutsumme "optimistiseksi muistinjakoksi". Se on samanlainen kuin Linuxin käyttämä copy-on-copy-kirjoitus, kun haarruit prosessia. Joten kun teet malloc () -sovelluksen, saat pääsyn virtuaaliseen muistiin, mutta todelliset sivut on allokoitava, kun käytät sitä muistia.

Luoko malloc laiskoilla varmuuskopiosivuja allokointiin Linuxissa (ja muilla alustoilla)?


Vastaus 2:

Calloc () -puhelu tulee aina olemaan hitaampi johtuen opportunistisesta allokaatiosta, kuten Robin Thomas huomautti. Jos varaat 100 Mt ja käytät vain ensimmäistä 4K, ydin ei kartoita muuta kuin yhtä sivua todellista muistia virtuaaliosoitetilassa. Se on enimmäkseen 4 kt, mutta voit käyttää getpagesize (tyhjää) määrittääksesi sivusi koon Unix-tyypeille.

Jos kirjoitat testiohjelman, joka käyttää mallocia allokoimaan 10 000 lohkoa ja sitten calloc allokoimaan 10 000 lohkoa, calloc tulee hitaammaksi yksinkertaisesti siksi, että malloc ei todellakaan tee mitään, vaan saa ytimen asettamaan lohkojen virtuaalisen osoitetilan. Mutta calloc () saa ytimen kävelemään kasan ja löytämään tarvittavan muistin ja kartoittamaan sen sitten ohjelman osoitealueeseen.

Kun ydin, kun kartoitetaan uutta muistia virtuaaliosoitetilaan, asettaa sen nollaan varmistaakseen, että et näe tietoja toisesta ohjelmasta. Mutta kun vapautat sen ja varaat sen samankokoiseksi tai pienemmäksi, saat todennäköisesti "vanhan" muistilohkon takaisin, kuten tässä on osoitettu:

# sisällytä 
# sisällytä 
# sisällytä 
# sisällytä 

print_mem (int * mem)
{
   int i;
   
   (i = 0; i <100, i ++, mem ++)
     printf ("% x", * mem);
}

int main (tyhjä)
{
   int * mem, i;
   
   printf ("Tämän kaarin muistisivut ovat:% d \ n", getpagesize ());
   
   // Malloc 100 tuumaa ja täytä ne kuolleena naudanlihalla
   mem = malloc (100 * sizeof (int));
   printf ("Vasta allokoitu mallocin kanssa \ n");
   print_mem (mem);
   (i = 0; i <100, i ++)
      * (Mem + i) = 0xdeadbeef;
   printf ("\ nKirjoittamisen jälkeen \ n");
   print_mem (mem);
   vapaa (MEM);
   printf ( "\ nFreed \ n");
   
   mem = malloc (100 * sizeof (int));
   printf ("\ nAsetettiin toinen muistikoko, samankokoinen \ n");
   // Tämä sisältää todennäköisesti 0xdeadbeef
   print_mem (mem);
   (i = 0; i <100, i ++)
      * (Mem + i) = 0xabbababe;
   printf ("\ nKirjoittamisen jälkeen \ n");
   print_mem (mem);
   vapaa (MEM);
   printf ( "\ nFreed \ n");
}

Käytän tosiasiassa glib-muistia kaikessa muistin allokoinnissa, mutta pidän silti g_malloc0: sta hyödyllistä, kun tiedän, että haluan koko muistin olevan nolla. Mutta vasta sitten. En tyhjentänyt muistia, ellei minulla ollut erityistä syytä siihen.

Suojausohjelmille on järkevää nollata se ennen kuin vapautat sen. Tämä varmistaa, että jos ohjelmaa hakkeroidaan, lisätty koodi ei pääse selaamaan kasaa ja nähdä vanhoja tietoja tekemällä suuri allokaatio ja yksinkertaisesti tutkimalla sitä (tai lähettämällä se pois tutkimusta varten).


Vastaus 3:

Calloc () -puhelu tulee aina olemaan hitaampi johtuen opportunistisesta allokaatiosta, kuten Robin Thomas huomautti. Jos varaat 100 Mt ja käytät vain ensimmäistä 4K, ydin ei kartoita muuta kuin yhtä sivua todellista muistia virtuaaliosoitetilassa. Se on enimmäkseen 4 kt, mutta voit käyttää getpagesize (tyhjää) määrittääksesi sivusi koon Unix-tyypeille.

Jos kirjoitat testiohjelman, joka käyttää mallocia allokoimaan 10 000 lohkoa ja sitten calloc allokoimaan 10 000 lohkoa, calloc tulee hitaammaksi yksinkertaisesti siksi, että malloc ei todellakaan tee mitään, vaan saa ytimen asettamaan lohkojen virtuaalisen osoitetilan. Mutta calloc () saa ytimen kävelemään kasan ja löytämään tarvittavan muistin ja kartoittamaan sen sitten ohjelman osoitealueeseen.

Kun ydin, kun kartoitetaan uutta muistia virtuaaliosoitetilaan, asettaa sen nollaan varmistaakseen, että et näe tietoja toisesta ohjelmasta. Mutta kun vapautat sen ja varaat sen samankokoiseksi tai pienemmäksi, saat todennäköisesti "vanhan" muistilohkon takaisin, kuten tässä on osoitettu:

# sisällytä 
# sisällytä 
# sisällytä 
# sisällytä 

print_mem (int * mem)
{
   int i;
   
   (i = 0; i <100, i ++, mem ++)
     printf ("% x", * mem);
}

int main (tyhjä)
{
   int * mem, i;
   
   printf ("Tämän kaarin muistisivut ovat:% d \ n", getpagesize ());
   
   // Malloc 100 tuumaa ja täytä ne kuolleena naudanlihalla
   mem = malloc (100 * sizeof (int));
   printf ("Vasta allokoitu mallocin kanssa \ n");
   print_mem (mem);
   (i = 0; i <100, i ++)
      * (Mem + i) = 0xdeadbeef;
   printf ("\ nKirjoittamisen jälkeen \ n");
   print_mem (mem);
   vapaa (MEM);
   printf ( "\ nFreed \ n");
   
   mem = malloc (100 * sizeof (int));
   printf ("\ nAsetettiin toinen muistikoko, samankokoinen \ n");
   // Tämä sisältää todennäköisesti 0xdeadbeef
   print_mem (mem);
   (i = 0; i <100, i ++)
      * (Mem + i) = 0xabbababe;
   printf ("\ nKirjoittamisen jälkeen \ n");
   print_mem (mem);
   vapaa (MEM);
   printf ( "\ nFreed \ n");
}

Käytän tosiasiassa glib-muistia kaikessa muistin allokoinnissa, mutta pidän silti g_malloc0: sta hyödyllistä, kun tiedän, että haluan koko muistin olevan nolla. Mutta vasta sitten. En tyhjentänyt muistia, ellei minulla ollut erityistä syytä siihen.

Suojausohjelmille on järkevää nollata se ennen kuin vapautat sen. Tämä varmistaa, että jos ohjelmaa hakkeroidaan, lisätty koodi ei pääse selaamaan kasaa ja nähdä vanhoja tietoja tekemällä suuri allokaatio ja yksinkertaisesti tutkimalla sitä (tai lähettämällä se pois tutkimusta varten).


Vastaus 4:

Calloc () -puhelu tulee aina olemaan hitaampi johtuen opportunistisesta allokaatiosta, kuten Robin Thomas huomautti. Jos varaat 100 Mt ja käytät vain ensimmäistä 4K, ydin ei kartoita muuta kuin yhtä sivua todellista muistia virtuaaliosoitetilassa. Se on enimmäkseen 4 kt, mutta voit käyttää getpagesize (tyhjää) määrittääksesi sivusi koon Unix-tyypeille.

Jos kirjoitat testiohjelman, joka käyttää mallocia allokoimaan 10 000 lohkoa ja sitten calloc allokoimaan 10 000 lohkoa, calloc tulee hitaammaksi yksinkertaisesti siksi, että malloc ei todellakaan tee mitään, vaan saa ytimen asettamaan lohkojen virtuaalisen osoitetilan. Mutta calloc () saa ytimen kävelemään kasan ja löytämään tarvittavan muistin ja kartoittamaan sen sitten ohjelman osoitealueeseen.

Kun ydin, kun kartoitetaan uutta muistia virtuaaliosoitetilaan, asettaa sen nollaan varmistaakseen, että et näe tietoja toisesta ohjelmasta. Mutta kun vapautat sen ja varaat sen samankokoiseksi tai pienemmäksi, saat todennäköisesti "vanhan" muistilohkon takaisin, kuten tässä on osoitettu:

# sisällytä 
# sisällytä 
# sisällytä 
# sisällytä 

print_mem (int * mem)
{
   int i;
   
   (i = 0; i <100, i ++, mem ++)
     printf ("% x", * mem);
}

int main (tyhjä)
{
   int * mem, i;
   
   printf ("Tämän kaarin muistisivut ovat:% d \ n", getpagesize ());
   
   // Malloc 100 tuumaa ja täytä ne kuolleena naudanlihalla
   mem = malloc (100 * sizeof (int));
   printf ("Vasta allokoitu mallocin kanssa \ n");
   print_mem (mem);
   (i = 0; i <100, i ++)
      * (Mem + i) = 0xdeadbeef;
   printf ("\ nKirjoittamisen jälkeen \ n");
   print_mem (mem);
   vapaa (MEM);
   printf ( "\ nFreed \ n");
   
   mem = malloc (100 * sizeof (int));
   printf ("\ nAsetettiin toinen muistikoko, samankokoinen \ n");
   // Tämä sisältää todennäköisesti 0xdeadbeef
   print_mem (mem);
   (i = 0; i <100, i ++)
      * (Mem + i) = 0xabbababe;
   printf ("\ nKirjoittamisen jälkeen \ n");
   print_mem (mem);
   vapaa (MEM);
   printf ( "\ nFreed \ n");
}

Käytän tosiasiassa glib-muistia kaikessa muistin allokoinnissa, mutta pidän silti g_malloc0: sta hyödyllistä, kun tiedän, että haluan koko muistin olevan nolla. Mutta vasta sitten. En tyhjentänyt muistia, ellei minulla ollut erityistä syytä siihen.

Suojausohjelmille on järkevää nollata se ennen kuin vapautat sen. Tämä varmistaa, että jos ohjelmaa hakkeroidaan, lisätty koodi ei pääse selaamaan kasaa ja nähdä vanhoja tietoja tekemällä suuri allokaatio ja yksinkertaisesti tutkimalla sitä (tai lähettämällä se pois tutkimusta varten).