Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

Graph cachen

Pagina: 1
Acties:

  • JJ93
  • Registratie: Maart 2013
  • Laatst online: 21-11 11:31

JJ93

Error 418

Topicstarter
Hoi,

Ik ben sinds drie weken bezig met het leren van PHP om wat statistieken op te slaan en te weergeven. Dat is aardig gelukt maar het laden van de pagina is erg sloom aangezien ik veel query's moet doen.

Ik berekenen voor zes verschillende skills voor level 1-99 het gemiddeld aantal xp per uur. Ik kom dus totaal uit op 600 queries en nog wat berekeningen. Misschien kan dit makkelijker maar het lijkt mij in ieder geval handig om de data te cachen. Of een plaatje weergeven van de resultaten. Vervolgens die data gebruiken of het plaatje om de paar minuten refreshen.

Dus ik vraag mij af hoe ik dit het beste kan doen. Ik gebruik highcharts om de grafiek te tekenen.
PHP code:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//Blablabla
        include('functions.php');
        // DATABASE CONNECTION
        $db_handle = mysqli_connect(*****) or die("Error connecting to database");

        // Sum of all statistics
        $SQL = "SELECT SUM(runtime) AS total_runtime, SUM(attack_xp) AS total_attack_xp, SUM(strength_xp) AS total_strength_xp, SUM(defence_xp) AS total_defence_xp, SUM(ranged_xp) AS total_ranged_xp, SUM(magic_xp) AS total_magic_xp, SUM(hitpoints_xp) AS total_hitpoints_xp FROM jjsfighter";
        $result = mysqli_query($db_handle, $SQL);
        if($result){
            $row = mysqli_fetch_assoc($result);
//Blablabla

            // Calculate xp/h statistics
            $skills = array("attack", "strength", "defence", "ranged", "magic", "hitpoints");
            $xprates = array(array());

            // Each skill
            for($i = 0; $i < sizeof($skills); $i++){
                // Each lvl
                for($j = 1; $j < 100; $j++){
                    // Select total xp for that skill at that level
                    $SQL = "SELECT SUM(" . $skills[$i] . "_xp) AS xp, SUM(runtime) AS time FROM jjsfighter WHERE " . $skills[$i] . "_lvl=$j AND " . $skills[$i] . "_xp > 0";
                    $result = mysqli_query($db_handle, $SQL);

                    // Check if the query is correct
                    if($result) {
                        $row = mysqli_fetch_assoc($result);
//Blablabla berekening(en)
                    }
                }
            }
        }   

        mysqli_close($dbhandle);
//Blablabla


In actie: http://obduro.org/scriptstats/jjsfighter.php

Ik zou mijn code graag optimaliseren. Zoals je merkt laadt alles nu erg langzaam in vergelijking met andere pagina's.

[ Voor 43% gewijzigd door RobIII op 18-10-2013 22:12 . Reden: Flink gesnoeid in irrelevante code ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik ben even zo vrij geweest je lap code (120+ regels) flink te snoeien tot enkel de relevante(!) delen code; niemand is geïnteresseerd in 't deel dat ik gesnoeid heb (de "blablabla") en zal je code dus lezen zoals 't er nu staat. JS, CSS en andere zaken die niet relevant zijn voor je probleem mag je gewoon weglaten; de essentie staat daarmee nog steeds. Wel wil ik je vriendelijk verzoeken dat voortaan zelf te doen; voor jou is 't een kleine moeite en 't helpt ons door de bomen 't bos te zien als we hapklare brokken krijgen aangereikt i.p.v. naalden in een hooiberg te moeten gaan zoeken.

Having said that: waarom in hemelsnaam zo'n shitload aan queries op je DB loslaten? Je zou moeten kunnen volstaan met 1 query per "skill" (wat het geheel dus reduceert aantal_skills * 100 tot aantal_skills queries, ofwel: 600 -> 6) en mogelijk zelfs met maar 1 query voor 't geheel. Ik zou als ik jou was eens even gaan kijken naar Hoe werkt dat GROUP BY nu eigenlijk?. Eventuele records die uit de resultset "ontbreken" omdat ze nul of non-existent zouden zijn handel je gewoon in af code/je view.

Als 't gebeuren daarna nog te traag zou zijn moet je je gaan concentreren op de juiste indices etc. in je table (en dat moet je eigenlijk ook doen als 't wel voldoende performed). En als dat allemaal op orde is moet je je druk gaan maken om 't cachen van de data (je resulset(s)) i.p.v. het cachen van grafieken. Die grafiek genereren kost niks (en gebeurt in jouw geval ook nog eens client-side) maar als je de data cached kun je diezelfde data ook gebruiken in een tabel of voor andere weergaven/grafiektypes etc. zonder daar (weer) queries voor af te moeten vuren. Cachen kun je doen in een file of in memcached en dat soort zaken, maar dat zijn allemaal implementatiedetails; ik zou eens beginnen bij 't begin ;)

[ Voor 35% gewijzigd door RobIII op 18-10-2013 22:18 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • JJ93
  • Registratie: Maart 2013
  • Laatst online: 21-11 11:31

JJ93

Error 418

Topicstarter
Ok, bedankt voor het snoeien, verschilt wel eens per forum wat ze willen hebben.. in dit geval was een deel niet erg relevant inderdaad.

Het is lijkt mij inderdaad niet het meest efficiente om 600 queries te doen.. Ik zat al te denken om in ieder geval een factor 100 minder queries te doen door in één keer per skill de resultaten op te halen. Kan natuurlijk gewoon per level.

Ik had het hele gebeuren eerst in een paar tabellen en het ging nog redelijk snel. Maar nu meer dan 5x zoveel data verzamelt dus nu merk je hoe traag het is.

Ik heb het nu deels herschreven en het werkt al een enorm stuk sneller dan eerst.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Calculate xp/h statistics
            $skills = array("attack", "strength", "defence", "ranged", "magic", "hitpoints");
            $xprates = array(array());

            // Each skill
            for($i = 0; $i < sizeof($skills); $i++){
                // Select total xp per level
                $SQL = "SELECT " . $skills[$i] . "_lvl AS level, SUM(" . $skills[$i] . "_xp) AS xp, SUM(runtime) AS time FROM jjsfighter WHERE " . $skills[$i] . "_xp > 0 GROUP BY level";
                $result = mysqli_query($db_handle, $SQL);

                // Loop through results
                if($result){
                    while ($row = mysqli_fetch_array($result)) {
                        // Time
                        $seconds = $row["time"];
                        $time = seconds_to_time($seconds);

                        // Xp
                        $xp = $row["xp"];
                        $xpperhour = round($xp / ($seconds/60/60));

                        // Store values
                        $lvl = $row["level"];
                        $xprates[$i][$lvl] = $xpperhour;
                    }
                }
            }


Het enige waar ik nog voor moet zorgen is dat niet bestaande levels een xp/h van -1 krijgen.
Misschien met array_key_exists() oid maar ik ga nu eerst maar eens slapen. Toch wat later worden dan gepland toen ik nog even naar dit topic keek of iemand gereageerd had.

[ Voor 6% gewijzigd door JJ93 op 19-10-2013 01:20 ]


  • JJ93
  • Registratie: Maart 2013
  • Laatst online: 21-11 11:31

JJ93

Error 418

Topicstarter
Ik heb het nu voor elkaar gekregen dat de standaard waarde -1 is. Ik wijs meteen -1 toe en definieer meteen de grootte van de 2d array. Hierdoor hoeft deze niet dynamisch verandert te worden tijdens het loopen. Het lijkt er op dat het nu dan ook sneller is dan de code hierboven (post #3)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Calculate xp/h statistics
            $skills = array("attack", "strength", "defence", "ranged", "magic", "hitpoints");
            $xprates = array_fill(0, sizeof($skills), array_fill(0, 99, -1));

            // Each skill
            for($i = 0; $i < sizeof($skills); $i++){
                // Select total xp per level
                $SQL = "SELECT " . $skills[$i] . "_lvl AS level, SUM(" . $skills[$i] . "_xp) AS xp, SUM(runtime) AS time FROM jjsfighter WHERE " . $skills[$i] . "_xp > 0 GROUP BY level";
                $result = mysqli_query($db_handle, $SQL);

                // Loop through results
                if($result){
                    while ($row = mysqli_fetch_array($result)) {
                        // Time
                        $seconds = $row["time"];
                        $time = seconds_to_time($seconds);

                        // Xp
                        $xp = $row["xp"];
                        $xpperhour = round($xp / ($seconds/60/60));

                        // Store values
                        $lvl = $row["level"];
                        $xprates[$i][$lvl] = $xpperhour;
                    }
                }
            }


In ieder geval is het echt een enorm stuk sneller dan de code van post #1. Bedankt voor de hulp. Vraag is beantwoord maar ik kan de eerste post niet meer bewerken.