kaktussoft
Laatste wijziging: 11-05-2017 09:37

Technische informatie

Onderstaande informatie is zeer technisch en bedoeld voor webdesigners en webdevelopers!

Client-kant

Met de client-kant bedoel ik hetgene dat op uw pc draait.
  • HTML: HTML-pagina's geladen vanaf een webserver. Binnen deze pagina's worden tevens CSS-bestanden en JavaScript-bestanden geladen.
  • CSS: Voor het aanmaken van CSS-klasses, zodat ik eenvoudig de kleuren, lettertypes, marges e.d. kan veranderen.
  • JavaScript: JavaScript-functies voor het uitvoeren van diverse taken. Voornamelijk voor het asynchroon aanroepen van een PHP-bestand op de webserver. Dit PHP-bestand geeft een JSON-object als antwoord. JavaScript kan dit JSON-object prima doorlopen (record voor record, veld voor veld). Tijdens dit doorlopen voegt hij HTML-codes toe, zodat het bijvoorbeeld wordt opgemaakt als tabel. Ook kan ik items klikbaar maken. Alle toegevoegde HTML-elementen voorzie ik van CSS-klasses dus zijn simpel aan te passen. Uiteindelijk wordt de gegeneerde HTML-code geïnjecteerd op een plek op de HTML-pagina (in een DIV-element).

    De JavaScript-functies worden aangeroepen vanuit een "event", bijvoorbeeld HTML-pagina is geladen, of u klikt op een HTML-element.
  • jQuery: jQuery is een JavaScript-bibliotheek waar je handige dingen mee kan doen. Ik gebruik momenteel $.getJSON voor het asynchroon ophalen van het JSON-object.

Middels javascript voorkom ik XSS. Tevens zijn er maatregelen tegen CSRF.

Performance Client-kant

http://kaktussoft.nl/voetbalpool/wk2014/stats.php toont in het blok "Overzicht van voorspelde landen per deelnemer per fase" de gegevens vanuit http://kaktussoft.nl/voetbalpool/wk2014/php/frvstatsdeelnemers.php . Onder andere wordt er een koppeling getoond naar spelergegevens. Tevens wordt veld "Landen" geanalyseerd en blauw getoond indien het team die fase nog actief was en doorgestreeptrood indien het team al in een eerdere ronde uitgeschakeld was. Verwerken in javascript tot een variable totstring duurt plm 20 ms voor 1000 deelnemers! (sterk afhankelijk van de snelheid van uw computer). Deze totstring injecteren in het html-document duurt dan 900 ms. Dit kan ik niet versnellen want ik doe het dmv de "property" innerHTML in een keer. Hierna rendeert de browser de pagina en dat duurt plm 5 seconde, wat ik uiteraard ook niet kan versnellen.

Alles gaat dus supersnel en het geeft alleen bij heel grote aantallen flinke vertraging wat ik niet kan verhelpen.

Server-kant

Met de server-kant bedoel ik hetgene dat op mijn linux-server draait.
  • APACHE: Webserver. Deze stuurt HTML-pagina's, CSS-bestanden en JavaScript-bestanden naar de client (uw pc). In geval het een PHP-bestand betreft dan wordt het eerst uitgevoerd op de linux-server, vervolgens wordt de uitvoer naar de client gestuurd (uw pc).
  • MYSQL: Database-server. Hierin staan de tabellen, views, indexen, triggers.
  • PHP: Programmeertaal. Deze gebruik ik voornamelijk om de database te bevragen.
    Normale query's:
    1. Login op database-server
    2. Zend SQL-query naar de database-server en zet het antwoord in een "resultset".
    3. Loguit van database-server.
    4. Loop door de resultset record voor record en voeg de records toe aan een array.
    5. Verwijder de resultset.
    6. Converteer de uiteindelijke array naar een JSON-object.
    7. Zend JSON-object naar aanvrager.
    Master-detail query's:
    1. Login op database-server
    2. Zend SQL-query1 naar de database-server en zet het antwoord in een "resultset1".
    3. Loop door de resultset1 record voor record en voeg de records toe aan een array (bijvoorbeeld teamnamen). Indien ik de teamnaam van record 1 weet kan ik een nieuwe sql-query maken en naar de database sturen en het antwoord in een array plaatsen. Deze array voeg ik toe aan record 1 als subarray. Daarna verwijder ik resultset2.
    4. Loguit van database-server.
    5. Verwijder de resultset1.
    6. Converteer de uiteindelijke array naar een JSON-object.
    7. Zend JSON-object naar aanvrager.

Ik "sanitize" alle gebruikersinvoer met behulp van PDO::prepare ter voorkoming van SQL injection.

Linux, Apache, Mysql, PHP

Performance Server-kant

Deze server zal onder andere dienen als webserver die statische informatie-pagina's aanlevert. Maar de hoofdzaak wordt het aanleveren van dynamische data door de webserver. Dit gebeurt mbv php en mysql. De webserver (apache) kan het gemakkelijk aan en de php bestanden zijn erg simpel, zie Technische info (sectie Server-kant). Ik focus me op de snelheid van mysql. Met Apache Benchmark belast ik de server. Bijvoorbeeld:

ab -n 10000 -c 50 http://localhost/biljart/test/php/wedstrijden_details.php

Dit benadert die pagina 10000 maal en doet dat met 50 parallelle verzoeken. Die webpagina is heel complex ... het toont elke wedstrijd en het zoekt voor elke wedstrijd de details op. Het zoekt dus 156 maal een wedstrijd op in de uitslagentabel (een master-detail query). Resultaten:
  • Verwerktijd van 10000 verzoeken is constant, ongeacht hoeveel er parallel draaien.
  • Gemiddeld plm 50 verzoeken kunnen er verwerkt worden per seconde.
  • 10 maal queryA en 10 maal queryB en 10 maal queryC enz maakt ook niet uit.
  • Schijfbenadering is bijna nihil. Tabellen zijn klein en alles zit gewoon in het geheugen.
  • Geheugen is geen probleem. Er is nog genoeg vrij. mysql settings zoals query_cache_limit, query_cache_size, thread_cache_size en innodb_buffer_pool_size houd ik goed in de gaten indien het langzamer wordt.
  • De eerste keer draaien van een query duurt aanzienlijk langer. Daarna wordt het antwoord echter in de "query cache" geplaatst en is het supersnel. Echter alleen indien de onderliggende tabellen niet veranderen. De query_cache_size is dus heel belangrijk!
  • Bottleneck is de cpu. Bij 10 verzoeken tegelijk gebruikt hij ook 10 maal zoveel cputijd.
  • Ook project WK2014 voetbalpool heb ik getest met (als test) 10000 deelnemers en dus 480000 wedstrijdvoorspellingen. Performance was zeer acceptabel.
Uit verdere analyse blijkt dat het aanmaken van het php-proces 0,3 ms duurt. Het "includen" van een bestand met speciale functies duurt 0,1 ms en het verbinden met mysql duurt 0,2 ms. Het verkrijgen van een antwoord op een sql-select duurt 0,1 ms indien het antwoord reeds eerder gecached is. Definiëren van een lege array, het leegmaken van de mysql-resultset en sluiten van de mysql-verbinding duren 0 ms. De duur van het omzetten van de mysql-resultset naar een array en het omzetten van de array naar een json-object is afhankelijk van het aantal records en het aantal velden. Globaal duurt het plm 1 ms per 50 records.

Conclusie: Zelfs bij 50 verzoeken tegelijk is zelfs de moeilijkste mysql select-opdracht (156 maal de uitslagentabel benaderen) geen probleem. Alle 50 verzoeken zijn na plm 1 seconde klaar. 50 parallelle verzoeken is trouwens een utopie ... een moeilijk verzoek duurt hooguit 20ms dus indien dat parallel gebeurt dan is dat vrij zeldzaam.

Ik heb de moeilijkste mysql select-opdracht (156 maal de uitslagentabel benaderen) herschreven. Hij haalt nu met 1 select-opdracht de hele uitslagentabel op. Daarna wordt het samengevoegd met de reeds opgezochte wedstrijden. Het duurt nu nog maar 5 ms.

Client-kant (ODBC)

Niet alle database functionaliteit wordt aangestuurd via de browser. Sommige functies gaan vanuit een database-programma op de pc. In mijn geval gebruik ik MS Access. Om dit mogelijk te maken dient de mysql ODBC connector geïnstalleerd te worden (32-bits versie want MS Access is zeer waarschijnlijk 32-bits).
  • Maak gekoppelde tabellen aan naar de mysql database. De tabellen zijn nu net zo te gebruiken als lokale tabellen.
  • Maak query's aan en master/detail datagrids. Gegevens zijn zo simpel aan te passen.
  • Maak update query's aan, bijvoorbeeld voor het aanpassen van de "te spelen" moyennes adhv de gemaakte caramboles en gespeelde beurten. Maak het een "pass through-query" indien de query helemaal op de server moet draaien (dan gaat het sneller). Maar dan kan je geen lokale tabellen en functies gebruiken.
  • U kunt in MS Access vba code maken die bijvoorbeeld een speelschema aanmaakt en in de database zet.
  • U kunt records veranderen, bijvoorbeeld teams of spelers toevoegen/veranderen.
  • U kunt overzichten maken en uitprinten of opslaan als pdf.
  • U kunt Excel-bestand met spelersnamen koppelen aan een lokale tabel. Vervolgens records van de gekoppelde tabel overzetten naar de mysql-tabel. U heeft de gegevens waarschijnlijk al in Excel, dus u kunt ze simpel importeren.

Indien u voorbeelden wilt zien van mijn JavaScript-, CSS-, of PHP-bestanden stuur mij dan een e-mail.

Mijn zelfgemaakte JavaScript-library (07-04-2017), Mijn javascript-code voor petanque website (07-04-2017), Maak sluitend wedstrijdschema (php) (07-04-2017). Zie petanque programma.