get_option() vs get_theme_mod(): De ce una este mai lentă?

18 iul. 2014, 23:06:04
Vizualizări: 27.7K
Voturi: 22

Am folosit get_theme_mod() pentru o perioadă în diverse proiecte ale mele. Am decis să profit de Theme Customization API din WordPress v3.4 odată ce a devenit disponibil, considerând că este un instrument indispensabil pentru clienții mei.

După un timp, am început să observ că site-urile mele deveneau puțin mai lente decât de obicei, iar Customizer-ul în special avea nevoie de mult timp pentru a se încărca. După numeroase încercări în timpul investigației mele, am decis să schimb parametrul type atunci când înregistrez setările (adică $wp_customize->add_setting()) din theme_mod în option.

După ce am făcut această modificare și am înlocuit toate apelurile get_theme_mod() cu get_option(), am observat o creștere foarte semnificativă a vitezei folosind cea din urmă configurație în comparație cu prima, atât în frontend cât și mai ales în Customizer în backend. Am căutat prin codul sursă WordPress încercând să găsesc un răspuns pentru această situație, dar nu am reușit să înțeleg care este problema specifică în acest scenariu.

Orice informații pe care comunitatea le-ar putea oferi cu privire la motivul pentru care get_option() funcționează semnificativ mai rapid decât get_theme_mod() ar fi foarte apreciate.

4
Comentarii

Dacă te uiți în directorul /wp-includes la fișierul option.php unde este definită funcția get_option(), și la theme.php unde este definită get_theme_mod(), poți vedea că aceasta din urmă apelează de fapt get_option() în sine, acționând ca o extensie a acesteia care aplică și filtrele necesare. Asta ar putea explica de ce este mai lentă.

Jody Heavener Jody Heavener
18 iul. 2014 23:20:51

Jody, și eu m-am gândit la asta, dar pare că simplul fapt de a face referire la get_option() și aplicarea unor filtre nu ar trebui să o încetinească atât de semnificativ cum se întâmplă. Cu siguranță un punct bun de plecare, dar mă întreb dacă nu cumva mai este ceva în spate.

ntg2 ntg2
19 iul. 2014 19:36:59

Nu există niciun motiv pentru o diferență de viteză acolo, așa că bănuiesc că altceva cauzează diferențele percepute de tine. Modificările de temă sunt stocate ca opțiuni în sine.

Otto Otto
19 iul. 2014 19:52:00

Ar putea procesul de serializare/deserializare în obținerea modului individual să joace un rol în acest sens? Sunt curios dacă acel efort suplimentar pentru a extrage modul ar putea fi o piedică în comparație cu simpla obținere a opțiunii fără a fi nevoie de acest pas. Când am făcut schimbarea de la get_theme_mod() la get_option(), viteza tuturor proiectelor s-a dublat în medie atât pe frontend cât și în Customizer. Aceasta a fost singura modificare făcută în încercarea de a o izola de orice alte efecte secundare.

ntg2 ntg2
19 iul. 2014 20:04:47
Toate răspunsurile la întrebare 5
0
23

Răspunsul este da, funcțiile theme_mod vor fi mai lente, dar nu semnificativ, iar beneficiile depășesc diferențele.

Setările temei (theme mods) sunt stocate ca opțiuni. Deci, în esență, funcțiile theme_mod sunt wrapper-uri în jurul funcțiilor de opțiuni.

Mai întâi, înțelegeți că setările theme_mod sunt stocate ca un array într-o singură opțiune, asociată numelui temei specifice. Deci, dacă fac asta:

set_theme_mod('aaa',123);
set_theme_mod('bbb',456);

Atunci ceea ce obțin de fapt în baza de date este un singur rând de opțiuni cu numele theme_mods_numeletemei care conține un array serializat cu ('aaa'=>123, 'bbb'=>456) în el.

Acum, get_theme_mod va fi mai lent pentru că de fapt face două apeluri get_option. Mai întâi, obține numele temei. Apoi, obține opțiunea theme_mods_numeletemei. Deci chiar aici avem o pierdere de viteză de 50%. Restul lucrării constă în mare parte în filtre, în sensul că există un apel suplimentar de filtru, dar dacă nu aveți ceva pe acel filtru, acest lucru este cam nesemnificativ.

Rețineți că sistemul de opțiuni stochează datele preluate în cache-ul de obiecte, deci nu se fac mai multe apeluri către baza de date aici. Doar prima utilizare duce la un acces la baza de date.

set_theme_mod va fi oarecum mai lent pentru că face aceleași două apeluri get options, apoi face încă un apel get_option pentru a obține din nou numele temei, iar apoi face update_option cu întregul set de opțiuni acum modificate. Acest lucru provoacă o actualizare a bazei de date, iar faptul că trimite mult mai multe date poate fi într-adevăr cauza unei încetiniri observabile. Actualizarea a câțiva octeți este mai rapidă decât actualizarea unui rând mai mare. Dar nu atât de mult încât să observați, de obicei. Doar dacă aveți o grămadă de setări...

Funcțiile theme_mod sunt probabil necesare pentru o optimizare generală, cu siguranță, dar tot ar trebui să le folosiți în loc de get_option și altele din cauza temelor copil.

Problema cu utilizarea directă a rândurilor de opțiuni este că le utilizați direct și folosiți nume specifice de chei pentru setările dumneavoastră.

Dacă am o temă numită "AAA" și fac o temă copil a acesteia numită "BBB" pentru utilizare pe un alt site, atunci tema mea "AAA" ar putea folosi o opțiune numită "exemplu". Când actualizez un site și acesta actualizează opțiunea mea, atunci aceeași opțiune se va aplica și temei mele copil. Ce se întâmplă dacă nu am vrut să se întâmple asta? Ce se întâmplă dacă am vrut ca tema copil să folosească un set diferit de opțiuni?

Theme mods, prin includerea numelui real al temei (și nu a unei valori hardcodate) ca parte a cheii, asigură că fiecare "temă" de pe site folosește propriul set de setări. Pot să trec de la una la alta și setările nu se transferă între ele, ele rămân așa cum le-am setat. Mai simplu, mai evident, mai intuitiv.

Și dacă vreo modificare viitoare a nucleului sau un plugin modifică modul în care funcționează theme_mods, atunci veți beneficia automat de aceasta fără nicio modificare. Wrapper-ele vor fi întotdeauna mai lente, acest lucru este inevitabil, este natura wrapper-elor. Cu toate acestea, tot scrieți cod PHP, nu limbaj de mașină. Folosim wrapper-e ca acestea pentru a simplifica lucrurile și a separa funcționalitățile. Temele nu ar trebui să știe sau să le pese cum sunt stocate opțiunile lor în baza de date sau cum funcționează denumirea. Funcțiile theme_mod oferă o soluție mai simplă care este mai curată.

21 sept. 2014 20:19:21
1

get_theme_mod este doar un înveliș în jurul funcției get_option. Teoretic, deoarece reprezintă un strat suplimentar de abstractizare, ar trebui să funcționeze mai lent, dar în practică diferența nu ar trebui să fie suficient de mare pentru a fi observată de om.

Diferențe reale de viteză pot apărea dacă aveți un cod lent atașat la hook-urile theme_mod.

20 iul. 2014 06:11:37
Comentarii

Nu este un wrapper. get_theme_mod stochează valoarea într-un array serializat împreună cu toate opțiunile temei într-un rând din tabelul wp_options, cu cheia predeterminată "theme_mods_<nume tema>". get_option stochează valoarea în câmpul option_value al unui rând din tabelul wp_options, cu o cheie pe care o specificați. Altfel spus, get_theme_mod grupează valoarea într-un array serializat cu toate celelalte modificări ale temei; get_option nu face acest lucru.

tklodd tklodd
26 iul. 2022 00:06:38
0

Ar putea fi ceva legat de Customizer? Observ același lucru ca și OP aici.

Pot confirma că, cu aproximativ 30 de opțiuni, timpul de încărcare al Customizer-ului meu a scăzut de la aproximativ 3 secunde la aproximativ 0,5 secunde când am trecut de la get_theme_mod la get_option.

Apelând metodele direct, observ o diferență de 2ms.

Rezultatele testelor (https://gist.github.com/anonymous/d98a46d00d52d40e7dec)

Diferența poate să nu fie vizibilă când compari API-urile direct, dar trebuie să fie ceva în modul în care sunt utilizate în Customizer.

22 iul. 2014 00:55:03
1

Poți TESTA TIMPUL pentru get_option (100 de iterații) folosind acest cod (introduce-l în functions.php sau altundeva):

add_action('wp','My_Test');
function My_Test(){
    var_dump(microtime(true));
    for ($i=1; $i<100; $i++) { get_option('blogdescription'); }
    var_dump(microtime(true));
    for ($i=1; $i<100; $i++) { get_theme_mod('blogdescription'); }
    var_dump(microtime(true));
    exit;
}   




Alte considerații

Nu știu dacă face vreo diferență (poate dezvoltatorii WordPress știu mai bine), dar m-am gândit că dacă un site are TRAFIC MARE și la fiecare încărcare de pagină trebuie să obțină sute de opțiuni, ce-ar fi dacă aș grupa mai multe opțiuni într-un singur get_option? Ca în exemplul următor:

update_option('my_extra_optss',  array(
      'myNAME' => 'George',
      'myAGE'  => 43 ));

apoi:

$x = get_option('my_extra_optss');
$x['myNAME'];
$x['myAGE'];
................

va face acest lucru site-ul puțin mai rapid?

11 iul. 2015 13:14:12
Comentarii

Exact asta face deja funcția get_theme_mod. Toate setările temei sunt deja combinate într-o singură opțiune. De fiecare dată când apelezi get_theme_mod, se fac două interogări la baza de date prima dată, iar apoi zero interogări la baza de date.

Otto Otto
17 sept. 2016 01:13:29
1

TL;DR: Dacă ești dezvoltator de teme, ar trebui să folosești get_theme_mod

Răspuns detaliat:

Dacă ai 100 de apeluri get_option, aceasta va efectua 100 de interogări în baza de date.

Dacă ai 100 de apeluri get_theme_mod, aceasta va efectua doar 1 interogare în baza de date.

De ce? Pentru că toate modificările temei sunt stocate într-un singur rând din baza de date și vor fi apelate o singură dată, în timp ce fiecare opțiune este un rând separat și 100 de apeluri get_option vor rezulta în 100 de interogări la baza de date, ceea ce, desigur, va încetini site-ul tău.

Dacă tema ta are multe opțiuni, folosirea get_theme_mod va reduce semnificativ numărul de interogări la baza de date.

Poți verifica performanța și numărul de interogări folosind Plugin-ul Query Monitor

9 iul. 2019 07:42:25
Comentarii

Acest lucru este ușor incorect. Funcția get_theme_mod folosește get_theme_mods - https://developer.wordpress.org/reference/functions/get_theme_mods/ - care de fapt execută 2 funcții get_option. Deci 100 de apeluri get_theme_mod fac de fapt doar 2 cereri către baza de date ;)

WPExplorer WPExplorer
15 apr. 2020 01:58:35