Ik ben bezig met een Android app die een HTML document moet parsen en de relevante delen aan de gebruiker moet laten zien. Tijdens het debuggen wil ik graag op veel plaatsen loggen waar de parser mee bezig is (bijv een stukje HTML) om te kunnen zien wat er mis gaat.
Het parsen van de HTML gaat echter VEEL langzamer met deze logs omdat ik vaak een heel stuk HTML wil loggen (bijvoorbeeld de contents van een bepaalde div) terwijl ik voor de applicatie zelf (als het eenmaal werkt) enkel een span nodig heb. Het opzoeken van die span gaat super snel (ik gebruik Jsoup voor het parsen), maar het ophalen van de hele parent-parent-parent-parent div (ik zeg maar iets) duurt veel langer. Dat maakt tijdens debug niet uit, maar zodra de app klaar is wil ik die debug statements met een simpele conditie uit kunnen zetten zodat dit in release mode niet de applicatie langzaam maakt.
Klinkt simpel, maar ik krijg het niet voor elkaar....
Ik heb een simpele conditionele log gemaakt met zoiets:
Simpel genoeg, en het doet wel wat het moet doen (het stuurt geen log als ik DEBUG = false zet), maar het probleem is dat ik deze functie wil aanroepen met de functie die heel lang duurt.
Stel dat ik een functie heb "getParentDivHtml" die 3 seconden er over doet om de html op te halen, wat ik alleen tijdens debug nodig heb. Ik wil dit dan op deze manier aanroepen:
Als DEBUG op false staat zou ik verwachten dat de compiler het hele 'log' statement hier uit zou halen. Dat doet het niet, zelfs in release mode duurt het nog steeds 3 seconden, ook al komt er geen log. Dit is ook wel logisch want 'getParentDivHtml' moet eerst draaien, dat duurt 3 seconden, en daarna komt pas de check of hij wel moet loggen. Die check wil ik echter wel graag in de log functie hebben anders moet ik die alsnog overal apart gaan checken en dat is natuurlijk niet handig.
Dit heb ik simpel gechecked met deze test:
Aanroepen met
zorgt er voor dat hij zelfs in release mode nog 3 seconden wacht.
Volgens mij moet de compiler toch wel slim genoeg zijn om te snappen dat dit niet nodig is? Of overschat ik nu de compiler?
Edit: ok, dat is natuurlijk niet waar, de compiler kan vast niet inschatten dat "testLongDebug" niks belangrijks doet. Maar m'n vraag blijft hetzelfde:
Hoe kan ik dit simpel oplossen? Wat ik dus wil is een enkele 'log' functie die ik overal waar ik maar wil kan aanroepen zonder eerst steeds een aparte check te hoeven doen op "!DEBUG", en dat moet vanzelf (zodra ik DEBUG = false zet) niet meer draaien, ook niet als het argument van de log functie log nodig heeft.
Het parsen van de HTML gaat echter VEEL langzamer met deze logs omdat ik vaak een heel stuk HTML wil loggen (bijvoorbeeld de contents van een bepaalde div) terwijl ik voor de applicatie zelf (als het eenmaal werkt) enkel een span nodig heb. Het opzoeken van die span gaat super snel (ik gebruik Jsoup voor het parsen), maar het ophalen van de hele parent-parent-parent-parent div (ik zeg maar iets) duurt veel langer. Dat maakt tijdens debug niet uit, maar zodra de app klaar is wil ik die debug statements met een simpele conditie uit kunnen zetten zodat dit in release mode niet de applicatie langzaam maakt.
Klinkt simpel, maar ik krijg het niet voor elkaar....
Ik heb een simpele conditionele log gemaakt met zoiets:
Java:
1
2
3
4
5
6
7
8
| private static final boolean DEBUG = true; // of false tijdens release private void log(String message) { if (!DEBUG) return; // in release hoeft dit niks te doen Log.d(TAG, message); } |
Simpel genoeg, en het doet wel wat het moet doen (het stuurt geen log als ik DEBUG = false zet), maar het probleem is dat ik deze functie wil aanroepen met de functie die heel lang duurt.
Stel dat ik een functie heb "getParentDivHtml" die 3 seconden er over doet om de html op te halen, wat ik alleen tijdens debug nodig heb. Ik wil dit dan op deze manier aanroepen:
code:
1
| log(getParentDivHtml()) |
Als DEBUG op false staat zou ik verwachten dat de compiler het hele 'log' statement hier uit zou halen. Dat doet het niet, zelfs in release mode duurt het nog steeds 3 seconden, ook al komt er geen log. Dit is ook wel logisch want 'getParentDivHtml' moet eerst draaien, dat duurt 3 seconden, en daarna komt pas de check of hij wel moet loggen. Die check wil ik echter wel graag in de log functie hebben anders moet ik die alsnog overal apart gaan checken en dat is natuurlijk niet handig.
Dit heb ik simpel gechecked met deze test:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| private static final boolean DEBUG = false; private void log(String message) { if (!DEBUG) return; // in release hoeft dit niks te doen Log.d(TAG, message); } private String testLongDebug() { try { Thread.sleep(3000); return "X after 3000 sleep"; } catch (InterruptedException ex) { return "X interrupted"; } } |
Aanroepen met
Java:
1
| log(testLongDebug()); |
zorgt er voor dat hij zelfs in release mode nog 3 seconden wacht.
Volgens mij moet de compiler toch wel slim genoeg zijn om te snappen dat dit niet nodig is? Of overschat ik nu de compiler?
Edit: ok, dat is natuurlijk niet waar, de compiler kan vast niet inschatten dat "testLongDebug" niks belangrijks doet. Maar m'n vraag blijft hetzelfde:
Hoe kan ik dit simpel oplossen? Wat ik dus wil is een enkele 'log' functie die ik overal waar ik maar wil kan aanroepen zonder eerst steeds een aparte check te hoeven doen op "!DEBUG", en dat moet vanzelf (zodra ik DEBUG = false zet) niet meer draaien, ook niet als het argument van de log functie log nodig heeft.