Table of Contents
Johdanto: Uudelleenarviointi toiminto kutsu yleiskatsaus
C-ohjelmointi, jokainen toimintokutsu tuo yläpuolella: kääntäjän täytyy työntää argumentteja pino (tai siirtää ne rekistereissä), hypätä funktion elin, suorittaa koodin ja sitten palata. Pieni, usein vetoavat toiminnot, tämä yläpuolella voi hallita suoritusaikaa, erityisesti suorituskykyä kriittisiä silmukoita tai syvään pesiytynyt toiminta. Moderni kääntäjät optimoida aggressiivisesti, mutta joskus ohjelmoijan on annettava selvä vihjeitä saavuttaa maksiminopeus. Yksi tällainen vihje on [] avainsana, joka kutsuu kääntäjän korvaamaan puhelun overline overline, parantaa Cache behavior, ja mahdollistaa edelleen kääntäjä optimoida, että cross funktion rajat.
Mekanismi Inline-toimintojen takana
Inline-toiminto ilmoitetaan avainsanalla. Tämä ei komenna kääntäjää inline; se on ehdotus. Kääntäjä voi jättää sen huomiotta toimintojen ollessa liian suuria, rekursiivisia tai kun optimointitasot ovat alhaiset. C99- ja myöhempien standardien semantiikkaa selvennettiin: otsikkotiedostossa [] määritellyllä toiminnolla voidaan sisällyttää moni käännösyksiköihin ilman päällekkäisyyttä tai linkitysvirheitä, edellyttäen, että ulkoinen määritelmä on olemassa jossain. Tämä saavutetaan usein tai -ilmoitusten yhdistelmällä.
- Staattinen inline:[ Funktio on sisäinen yhteys; jokainen käännösyksikkö saa oman kopion. Tämä on turvallisin ja kannettavin lähestymistapa pieniin apuri toimintoja määritelty otsikot.
- Esilinja (C99):[] Inline määritelmä tarjoaa kehon inlining, mutta ulkoinen määritelmä on oltava erillinen (yleensä yhdessä .c tiedosto). Vuonna C11 ja myöhemmin, tämä käyttäytyminen oli yhdenmukaistettu.
- Linja ilman staattista tai ulkoista:[] C99:ssä tämä on samanlainen ulkoisen inlinen; C11:ssä ulkoiset määritelmät vaaditaan vain, jos toimintoa ei ole inlined. Käytännössä on suosittu useimmissa käyttötapauksissa.
Avain oivallus:[] Inlining ei ole ilmainen lounas. Kääntäjä analysoi kustannus-hyöty vaihto-off: lisäämällä funktion kehon jokaisella puhelulla sivuston kasvaa koodin koko (koodi bloat), joka voi vähentää ohjevälimuistin tehokkuutta. Näin ollen inline on parasta varata pienille, usein kutsutaan toimintoja.
Kun Inline Functions Excel: Käytä tapauksia ja parhaita käytäntöjä
Pienet matemaattiset toiminnot
Toiminnot, jotka suorittavat alkeet aritmeettinen ... kuten tietojenkäsittely neliö, puristus arvo, tai testaaminen merkki .
static inline int clamp(int value, int low, int high) {
return (value < low) ? low : (value > high) ? high : value;
}
Lisävarusteet ja mutatoritoiminnot datarakenteissa
Objekti-oriented kuviot C usein käyttää getters ja setters tiivistää tietoja. Ilman inlining, nämä triviaali toiminnot lisäävät tarpeettomia yläpuolella:
typedef struct {
int x, y;
} Point;
static inline int point_get_x(const Point *p) {
return p->x;
}
static inline void point_set_x(Point *p, int x) {
p->x = x;
}
Upotetut järjestelmät ja reaaliaikainen koodi
Ympäristöissä, joissa on rajallinen pino-tila ja deterministinen ajoitusvaatimukset, inline toiminnot poistavat tarpeen työntää / pop pino kehysten, vähentää sekä latenssi ja muistin käyttöä. Kuitenkin koodikokoa on seurattava huolellisesti muistin rajoitteiset mikro-ohjaimet.
Kun ei riviin
- Suuri toiminnot:[] Sisäänrakennettu 100+ linja toiminto useita puheluja sivustoja turpoaa binäärinen ja todennäköisesti heikentää suorituskykyä vuoksi ohjevälimuistin paine.
- Käännöstoiminnot:[ Rekursiota ei voida täysin inlined (vaikka kääntäjä voi olla pois joitakin tasoja).
- Loopioinnit:[] Suuren silmukan sisältävän toiminnon kytkemisestä ei välttämättä ole merkittävää hyötyä.
- Rajallisesti kutsutut toiminnot:[ Ylivoima on mitätön, jos toimintoa kutsutaan harvoin; se vain tuhlaa tilaa.
Inline toiminnot Versus Macros: yksityiskohtainen vertailu
Ennen avainsanaa oli standardi, C ohjelmoijat käyttivät makroja ([) saavuttaakseen "inlining" . Mutta makrot ovat tekstisubstituutioita, eivät toimintoja. Niissä on vakavia haittoja:
- ]Type safety:[ Makrot eivät välitä tyypeistä. Pahamaineinen makro arvioi argumentteja useita kertoja, mikä johtaa vaarallisiin sivuvaikutuksiin käytettäessä sellaisia ilmaisuja kuin .
- Vianetsintä: [ Makrot katoavat esikäsittelyn aikana; vianetsintälaitteet eivät voi astua niihin.
- Komponentit lausumat:[] Moninkertainen makrot edellyttävät rumia leikkauksia (esim. ).
- Nimitörmäykset:[ Makrolaajennukset voivat häiritä paikallisia muuttujia.
Inline toiminnot voittaa kaikki nämä kysymykset: ne ovat todellisia toimintoja Type check, laajuudeltaan, ja sivuvaikutus-turvallinen argumentointi arviointi. Ne osallistuvat säännöllisen tyyppijärjestelmän ja voidaan debugged. Ainoa teoreettinen etu makros on, että niitä voidaan käyttää [] tyyppi-generic[] toiminnot . mutta C11 ja C23 [ ehdotukset ovat vähentää jopa tätä aukkoa.
Neuvosääntö:[] Mieluummin toimii makrojen päällä minkä tahansa funktion allekirjoitukseen sopivan logiikan osalta. Varaa makrot vain yksinkertaisille vakioille tai kuponkiliitolle.
Käytännön esimerkkejä: Inline Functions in Action
Esimerkki 1: Square (Ajulkaistu)
static inline int square(int x) {
return x * x;
}
Kääntäjä ei todennäköisesti lähetä puhelun opetusta lainkaan; koodista tulee yksinkertaisesti jokaisella puhelupaikalla.
Esimerkki 2: Tarkistaminen Jos merkki on Digit
static inline int is_digit(char c) {
return c >= '0' && c <= '9';
}
Esimerkki 3: Fast Min/Max (Max-arvon välttäminen)
static inline int imax(int a, int b) {
return (a > b) ? a : b;
}
Toisin kuin makroversio, tämä arvioi ja täsmälleen kerran välttäen kaksinkertaisen arvioinnin riskejä.
Esimerkki 4: Bit Operations (Unions or Byte Swapping)
static inline uint16_t swap_bytes(uint16_t x) {
return (x << 8) | (x >> 8);
}
Tämä on yksi ohje ARM:stä tai pyöritys x86:ssa, kun se on inline-muodossa.
Kompelointioptimistit ja Inline-avainsana
avainsana on vain yksi tekijä kääntäjän inlining-päätöksessä. Useimmilla kääntäjillä on komentorivin liput, jotka ohjaavat aggressiivisuutta:
- ]GCC/Clang:[] [ mahdollistaa kohtalaisen inliningin mahdollistaa aggressiivisemman inliningin. lippu voidaan nimenomaisesti ottaa käyttöön. Voit pakottaa tietyn toiminnon kytkemiseen riippumatta kääntäjäheuristiikasta, käytä tai tai sitä korkeammalla.
- MSVC:[ avainsana on käytettävissä, mutta se ei takaa inlineing (kääntäjä voi edelleen kieltäytyä tiettyjen toimintojen).
Esimerkki GCC-attribuutilla:
static inline __attribute__((always_inline)) int triple(int x) {
return x * 3;
}
Suorituskyvyn kannalta kriittisen koodin osalta on suositeltavaa tarkastaa luotu kokoonpano (esim. GCC:n tai ) avulla, että inlining tapahtui. Nykyaikaiset kääntäjät voivat inline-toiminnot, joita ei ole merkitty , korkealla optimointitasolla, ja vastaavasti ne voivat jättää huomiotta toimintojen osalta, jotka aiheuttaisivat liiallista koodin kasvua.
Mahdolliset jäljet: Koodi Bloat ja Binary Size
Jokaisen kutsun antaminen monissa paikoissa käytettävälle toiminnolle voi lisätä merkittävästi tekstisegmentin kokoa. Tämä on erityisen ongelmallista:
- Libraries:[ Inline toiminnot otsikoissa laajentaa kaikkiin käännös yksiköihin, jotka sisältävät ne, mahdollisesti moninkertaistaa koodin koko.
- Embedded systems:[ Flash ja RAM ovat rajalliset. 10-tavuinen funktio, jota käytetään 1000 paikasta, lisää lähes 10KB koodia.
- Ohjevälimuisti: [ Suurempi koodi voi aiheuttaa lisää välimuistin ohituksia, hidastaa koko ohjelmaa.
Käytä koodin turpoamisen vähentämiseksi vain aidosti pieniin toimintoihin (tyypillisesti 1...5. lausetta). Käytä profilointeja kuumien toimintojen tunnistamiseen ennen sokkoliningiä. Mittaa sekä suoritusaika että binäärikoko.
Inline toiminnot C standardien
avainsana otettiin käyttöön ]C99[]:ssä ja selvennettiin :ssä [[] ja :ssä. C23 säilyttää samat semantit ja joitakin lisäparannuksia. Historiallinen erottelu "inline-määritelmän" ja "ulkoisen määritelmän" välillä aiheutti sekaannusta. Nykyajan käytännössä useimmat hankkeet käyttävät yksinomaan, mikä sivuuttaa hienosteet. Tämä malli toimii kaikkien C-standardien kanssa C99:stä eteenpäin ja välttää linkkivirheet.
Jos sinun täytyy tukea C99-kääntäjiä (joka on yhä harvinaisempaa), sinun täytyy palata makroihin tai ulkoisiin otsikon-vain implementointeihin. Muuten, ota kannettavaksi ja tyyppiturvalliseksi vaihtoehdoksi.
Johtopäätös: Strateginen työkalu suorituskykyinsinöörin työkalusarjassa
Inline toiminnot ovat kypsä, hyvin määritelty ominaisuus C-kielen, että kun sovelletaan järkevästi, voi tuottaa mitattavissa nopeus parannuksia poistamalla toimintokutsun yläpuolella ja mahdollistaa ristitoiminnat optimointia. Ne ovat parempia makros lähes kaikissa nykyaikaisissa olosuhteissa. Avain on rajoittaa niiden käyttöä pieniin, kuumiin toimintoihin ja tarkistaa lopputulos profilointi ja kokoonpanon tarkastus. Yhdessä sopiva kääntäjä liput, inline toiminnot tekevät C-koodi sekä nopea ja ylläpidettävissä .
Lisätietoja saa GCC:n asiakirja-aineistosta, joka koskee inline-toimintoja[, ja :n viittausmerkintä ][[]]. Reaalimaailman suorituskyvyn analyysia varten [ tässä ACM-jonoartikkelissa [ tutkitaan yksityiskohtaisesti vaihtokauppojen tekemistä.