Inhoudsopgave Inhoudsopgave ......................................................................................... 1 Dankwoord .............................................................................................. 7 Voorwoord ............................................................................................... 8 Projectsamenvatting.................................................................................. 9 Projectfiche ............................................................................................ 10 Projectdefinitie ....................................................................................... 12 Inleiding ................................................................................................ 15 Wat is benchmarken ............................................................................. 15 Soorten benchmarks............................................................................. 15 Benchmarken in combinatie met monitoren ............................................. 16 Resultaten........................................................................................... 16 Build environement .............................................................................. 16 Taal................................................................................................. 16 Ontwikkelingspakket .......................................................................... 17 SharpDevelop add-in tree architecture.................................................. 17 Inleiding........................................................................................ 17 Add-in bestanden ........................................................................... 18 Probleemstelling ..................................................................................... 20 Inleiding ............................................................................................. 20 Connectieprobleem............................................................................... 20 Oplossing ......................................................................................... 20 Connectie aantal correct bepalen ...................................................... 20 Code .......................................................................................... 21 Een wachttijd bij het vragen van een nieuwe connectie ........................ 22 Andere problemen ................................................................................ 23 As Soon As Possible benchmarken ............................................................. 24 Inleiding ............................................................................................. 24 Databaseservers .................................................................................. 24 Code ............................................................................................... 29 Codegeneratie ................................................................................ 29 Benchmarken zelf ........................................................................... 30 Webservers ......................................................................................... 31 Code ............................................................................................... 35 Codegeneratie ................................................................................ 35 Benchmarken zelf ........................................................................... 36 Socketservers ...................................................................................... 36 Inleiding .......................................................................................... 36 Voorstudie........................................................................................ 37 Inleiding........................................................................................ 37 De klasse ‘ClientSocket’ ................................................................... 38 Hoe gebruiken .................................................................................. 39 Code ............................................................................................... 43 Codegeneratie ................................................................................ 43 Benchmarken zelf ........................................................................... 43 Continuous Rate benchmarken.................................................................. 45 Inleiding ............................................................................................. 45 Databaseservers .................................................................................. 46 Code ............................................................................................... 46 Codegeneratie ................................................................................ 46 Benchmarken zelf ........................................................................... 46 Webservers ......................................................................................... 48
Code ............................................................................................... Codegeneratie ................................................................................ Benchmarken zelf ........................................................................... Socketservers ...................................................................................... Code ............................................................................................... Codegeneratie ................................................................................ Benchmarken zelf ........................................................................... Monitoring ............................................................................................. Lokaal ................................................................................................ Een ander machine: servermonitoring ..................................................... Inleiding .......................................................................................... APUS Performance Monitoring Protocol ................................................. Inleiding........................................................................................ Serverconfiguratie instellen .............................................................. Sleutelwoorden............................................................................ Resultaat .................................................................................... Serverconfiguratie opvragen............................................................. Sleutelwoorden............................................................................ Resultaat (teruggekregen data) ..................................................... Ruwe info ...................................................................................... Sleutelwoorden............................................................................ Resultaat (teruggegeven data)....................................................... Gedetaileerde info........................................................................... Sleutelwoorden............................................................................ Resultaat (teruggegeven data)....................................................... Andere .......................................................................................... Sleutelwoorden............................................................................ Resultaat .................................................................................... Lokaal: De APUS kant ........................................................................ Monitoren in combinatie met een benchmark ...................................... Server: APUS SMT ............................................................................. Inleiding........................................................................................ Structuur van APUS SMT.................................................................. TaskHandler................................................................................... Communicatie met APUS ................................................................. StartListening .............................................................................. WDYH ........................................................................................ RQ;RI......................................................................................... Logging ...................................................................................... PerformanceInfoContainer................................................................ Grafisch...................................................................................... Code .......................................................................................... Uitbreidbaarheid van APUS SMT ..................................................... APUS SMT Gebruiken ...................................................................... Tclap.......................................................................................... Mogelijke parameters ................................................................... Besluit................................................................................................... Conclusies ............................................................................................. Leandro Cavaliere ................................................................................ Dieter Vandroemme ............................................................................. Lijst van afbeeldingen.............................................................................. Bijlagen .................................................................................................
48 48 49 51 52 52 52 55 55 55 55 55 55 55 55 55 56 56 56 56 56 57 58 58 58 58 58 58 58 62 63 63 64 64 65 65 65 66 67 69 70 70 71 72 72 73 74 75 75 76 77 78
Projectweken Dieter Vandroemme .......................................................... 78 Inleiding .......................................................................................... 78 De usercontrol: fase één .................................................................... 78 Inleiding........................................................................................ 78 De beginsituatie ............................................................................. 79 De eindsituatie ............................................................................... 80 Al verwezenlijkt ........................................................................... 80 Te verwezenlijken ........................................................................ 81 Korte toelichting ............................................................................. 81 Afhankelijkheden ......................................................................... 81 Groepen ..................................................................................... 81 Statementlist............................................................................... 81 Add-in based ............................................................................... 82 De usercontrol: fase twee ................................................................... 83 Inleiding........................................................................................ 83 Add-in based ontwikkelen ................................................................ 83 De add-in tree en add-in bestanden................................................ 83 Hoe ik dit toegepast heb ............................................................... 85 Slot............................................................................................ 88 Projectweken Leandro Cavaliere ............................................................. 89 Inleiding .......................................................................................... 89 Powermeter ...................................................................................... 89 Inleiding........................................................................................ 89 Overzicht....................................................................................... 89 PmConnection ............................................................................. 89 ValuePM ..................................................................................... 91 De termios klasse ........................................................................... 91 Praktijk (code uitleg) .................................................................... 91 Vereiste instellingen voor de Extech 380801 ....................................... 92 De rts lijn disablen is een must ...................................................... 92 Open ............................................................................................ 92 Read & Write.................................................................................. 92 Write.......................................................................................... 92 Read .......................................................................................... 93 Protocoll Extech 380801 .................................................................. 93 Soorten bytes.............................................................................. 93 Data blocks ................................................................................. 93 Performance Info ophalen...................................................................... 98 CPU ................................................................................................. 98 Windows ....................................................................................... 98 Win32_Processor ......................................................................... 98 Hoe ophalen................................................................................ 98 Linux ............................................................................................ 98 Gebruikte bestanden .................................................................... 98 Verklaring ................................................................................... 99 Hoe Parsen ................................................................................100 Berekening ................................................................................101 Geheugen .......................................................................................101 Windows ......................................................................................102 Gebruikte klassen .......................................................................102 Hoe ophalen...............................................................................102 Linux ...........................................................................................102
Gebruikte bestanden ...................................................................102 Verklaring ..................................................................................102 Hoe Parsen ................................................................................103 Disk ...............................................................................................104 Windows ......................................................................................104 Gebruikte wmi klassen.................................................................104 Hoe ophalen...............................................................................104 Linux ...........................................................................................105 Gebruikte bestanden ...................................................................105 Verklaring ..................................................................................105 Hoe Parsen ................................................................................106 Netwerk ..........................................................................................107 Windows ......................................................................................107 Gebruikte WMI klassen ................................................................107 Hoe ophalen...............................................................................107 Linux ...........................................................................................107 Gebruikte bestanden ...................................................................107 Verklaring ..................................................................................108 Hoe Parsen ................................................................................108 Berekening ................................................................................108 Conclusie ........................................................................................109
Dankwoord In de eerste plaats willen wij graag Johan De Gelas en Brecht Kets bedanken voor hun technische ondersteuning. Ook willen wij hen bedanken voor het vertrouwen die zij in ons gesteld hebben om dit project tot een goed einde te brengen. Verder zouden wij graag Jef Daels, Ingrid Viaene en Hans Ameel willen bedanken en de rest van het docentenkorps waarbij we met onze vragen terecht konden. Zo ook onze ouders waardoor het mogelijk was deze opleiding te doen en in het bijzonder willen wij ook ons team bedanken voor de fijne sfeer en de aangename tijd die we in het lab mochten doorbrengen.
Figuur 1: Het Sizing Servers team
Voorwoord Als twee ambitieuze studenten was het voor ons een buitenkans om aan dit project mee te werken. Zo kwamen we in aanraking met enkele Vlaamse KMO ’s: - Debreuck & Neirynck (Ieper) - EnergyICT – Energie monitoring & beheer (Kortrijk) - IndieGroup - Collaborative software (Kortrijk) - MCS - Facility management software (Antwerpen) - Minoc Online – Top 10 IT website (Turnhout) - Network en Storage Solutions – Pre Press software (Pittem) - Savaco – Server & netwerk integrator (Kortrijk) Waarvoor ons project gebruikt wordt om onderzoek te verrichten door het research team: Elisabeth van Dijk, Jens Delagrange en Stijn Verslycken. En enkele grotere bedrijven zoals bijvoorbeeld Intel die wat meer uitleg gaven over de nieuwste technologie op het vlak van servers en bedrijven zoals Supermicro waar we enkele van hun toestellen mogen gebruiken om te testen. Dit onderzoek houdt dan in dat met behulp van onze tool de schaling van een server kan worden gemeten op een eenvoudige en goedkope wijze. Zo kan om een voorbeeld te geven nagegaan worden bij welk aantal gebruikers het toestel begint te vertragen en hoeveel stroom die verbruikt. Indien u meer vragen hebt over de dienstverlening van het project ‘Sizing Servers’ kunt u terecht bij onze coach en bij onze projectbegeleider respectievelijk: Johan De Gelas (
[email protected]) en Brecht Kets (
[email protected]).
Het software team: Leandro Cavaliere (
[email protected]) Dieter Vandroemme (
[email protected])
Projectsamenvatting Stages voor laatstejaarsstudenten
Multimedia & Communicatie Technologie Academiejaar 2006-2007 Student :
Student :
VANDROEMME DIETER
CAVELIERE LEANDRO
Jan Frans Willemslaan 6, 8630 Veurne
Cockerillplaats 2, 3600 Genk
Email:
[email protected]
Email:
[email protected]
Optie: OA
Optie: NW
Stagetitel: Sizing Servers: APUS stress-testing en monitoring tool
Stageomschrijving: Twee studenten werken verder aan de ontwikkeling van APUS een stress-testing tool, uniek in de IT-wereld, die ontwikkeld werd om een antwoord te bieden aan de tekortkomingen van de industriële benchmarks. De hoofdopdracht is het ontwikkelen van een dynamische socket-library (c#) en van de servermonitoring tool (c++, Linux + Solaris). De studenten hebben veel inbreng in het uitvoeren van deze basisopdracht. Daarnaast is er nog ruimte voor eigen uitbreidingen. De stagair zal zowel met Vlaamse als buitenlandse bedrijven in contact komen. In samenwerking met: HOGESCHOOL WEST-VLAANDEREN DEPARTEMENT PIH Graaf Karel de Goedelaan 5
8500 Kortrijk
Externe stagebegeleider:
Stagecoach PIH:
Kets Brecht
De Gelas Johan
Projectfiche
Projectfiche Stage Multimedia & Communicatietechnologie 2006-2007 1. Projectmedewerker(s): Vandroemme Naam: Dieter Voornaam: OA Optie Naam: Voornaam: Optie:
ProjectID :
Cavaliere Leandro NW
2. Begeleiders: Hogeschool West-Vlaanderen Naam bedrijf : Begeleider van het bedrijf : Kets Naam: Brecht Voornaam: Coach van MCT: De Gelas Naam: Johan Voornaam: 3. Projecttitel: Sizing Servers: APUS stress-testing en monitoring tool
4. Projectopgave: Twee studenten werken verder aan de ontwikkeling van APUS een stress-testing tool, uniek in de IT-wereld, die ontwikkeld werd om een antwoord te bieden aan de tekortkomingen van de industriële benchmarks. De hoofdopdracht is het ontwikkelen van een dynami
5. Input: Apus Stress Tool: De student werkt verder op de bestaande architectuur. Server Monitor: De student begint van niets, en heeft enkel als referentie een (basis) monitor op Windows.
6. Output: Apus Stress Tool: Een socket library, samen met een addin-based stresstest en een omgeving die de gegevens van de server monitor kan visualiseren. Server Monitor: Een server monitor af, geschreven in c++, die cpu, geheugengebruik, hd-gebruik en stroomverbruik.
704
7. Criteria om succes te meten: De output
8. Wat het project niet realiseert:
10. Planning: ID 1
Milestones Af hebben van de conncurrent rate benchmark.
Verantwoordelijk Timing (einddatum) Dieter 23/03/2007
2
De server monitor zowel de client als de stress test tool.
Dieter en Leandro 21/04/2007
3
Het af hebben van de socketlibrary.
Dieter en Leandro 15/06/2007
Projectmedewerker(s) : Naam: Datum: Handtekening:
Vandroemme Dieter 22/03/2007
Naam: Datum: Handtekening:
Cavaliere Leandro 22/03/2007
Projectbegeleider(s): Naam: Datum: Handtekening:
Brecht Kets 22/03/2007
Naam: Datum: Handtekening:
De Gelas Johan 22/03/2007
11. Handtekening:
12
Projectdefinitie APUS staat voor APplication Unique Stresstesting en is de officiële naam van het project ‘Sheridan’ wat de codenaam is. De bedoeling van dit project is dan ook niet veranderd. Die is nog altijd, ik quoteer: ‘Een nieuw softwareproject kan de systeembeheerder voor een groot vraagteken plaatsen: is de huidige beschikbare server krachtig genoeg om de nieuwe database software intensief te laten gebruiken? Indien een nieuwe server aangeschaft wordt, in welke hardwarecomponenten moet er extra geïnvesteerd worden om flessenhalzen te voorkomen? Wat als er in de toekomst veel meer of intensiever gebruikt gemaakt wordt van deze applicatie? De softwareontwikkelaar die een goede service wil leveren naar zijn klanten toe heeft soortgelijke vragen: hoe goed schaalt de ontwikkelde database applicatie op de aanwezige servers van de klant? Hoe kan hij of zij hard maken dat de software wel degelijk zal schalen met intensiever gebruik, meer gebruikers of een combinatie van beide? Leveren de aangeprezen optimalisaties in de nieuwste versie werkelijk betere prestaties bij intensief gebruik? De huidige benchmark tools zoals TPC1 kunnen hierop geen antwoord bieden. Omdat deze benchmarks ontworpen zijn om vooral de hardwarefabrikanten en database software vendors de kans te geven om hun product te onderscheiden van de competitie, heeft de gemiddelde systeemadministrator en softwareontwikkelaar geen boodschap aan deze benchmarks. De testmethodes zijn complex, arbeidsintensief, duur en vereisen een heel netwerk van clients. Zelfs al slaagt men erin om de benchmark succesvol uit te voeren, dan zijn de resultaten weinig relevant voor de eigen situatie: de database applicatie gebruikt in de benchmark, wijkt meestal sterk af van het eigen software project.’
1
Transaction Processing Performance Council (TPC) is een not-for-profit organisatie welke performance benchmarks uitvoert voor IT applicaties, zoals bijvoorbeeld databases. Meer info op : http://www.tpc.org. Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
13
Figuur 2: Vergelijking TCP met Sheridan (APUS) ‘Het PWO1 project “Sizing Servers” wil nieuwe methodologieën en softwaretools (Sheridan) aanreiken die een antwoord bieden op bovenstaande vragen.’
1
Projectmatig Wetenschappelijk onderzoek.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
14
Figuur 3: Visie van Sheridan (APUS)
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
15
Inleiding Wat is benchmarken De term ‘benchmarken’ kan voor allerhande dingen worden gebruikt, zo kan de efficiëntie van een productieomgeving ook gemeten worden. En dit voorbeeld geeft dan ook meteen de algemene omschrijving van benchmarken terug, namelijk: Kijken hoe efficiënt iets gebeurt. Specifiek voor ons is benchmarken het testen van allerhande servers. Het unieke aan dit project is dat vanuit één applicatie verschillende gebruikers kunnen worden gesimuleerd. Niet dat het al niet mogelijk was om een server te testen, maar dit kan enkel via bijvoorbeeld het al eerder, in de projectdefinitie, vermelde TCP. Zoals eerder gezegd is bouwt deze stage verder op het project ‘Sheridan’ van vorig jaar, officieel benoemd tot ‘APUS’. Dan werd er immers veel onderzoek gedaan naar verschillende databaseservers zoals Sqlserver, MySql,… en nagedacht over hoe het programma er moest uitzien. Het geheel oogde al zeer professioneel en één specifieke benchmark is uit de bus gekomen, namelijk een type waarbij zoveel mogelijk queries in een zo kort mogelijke tijd worden afgevuurd. Deze kreeg de toepasselijke naam ‘As Soon As Possible’. Dit jaar werden er enkele grote en minder grote problemen in dit systeem opgelost en werd er een nieuw type benchmark toegevoegd. Ook werd het mogelijk om webservers en socketservers te testen.
Soorten benchmarks De twee beschikbare soorten benchmarks zijn ‘As Soon As Possible’ (ASAP) en ‘Continuous Rate’ (CR). De beide types zijn bruikbaar om zowel databaseservers, webservers en socketservers te testen. As Soon As Possible benchmarking betekent dat er in een zo ’n kort mogelijke tijd zoveel mogelijk requests1 naar de server worden gestuurd.
1
Een instructie naar de server toe, in het geval van databases is dit een query.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
16
Continuous Rate Benchmarken verschilt er dan in dat er een wachttijd tussen de verschillende requests kan ingesteld worden om zo gebruikers realistisch te simuleren. Bijvoorbeeld: Gemiddeld om de twee seconden klikt een gebruiker op een link in een website.
Benchmarken in combinatie met monitoren U kunt indien u dit wenst een server monitoren, het toestel volgen op CPU gebruik, harde schijf gebruik, … en zelfs stroomverbruik. Hiervoor werd een tool ontwikkeld, APUS Server Monitoring Tool (SMT), voor zowel het Windows als het Linux platform. Deze tool kan lokaal op het toestel gebruikt worden om alles in de gaten te houden en kan deze info dan wegschrijven naar een tekstbestandje. Vanuit APUS zelf kan er ook een connectie naar APUS SMT worden gelegd om zo over het netwerk de server te kunnen monitoren. Hierbij kunnen allerhande instellingen worden gemaakt zoals het loggen op de server aan of uit zetten. Dit kan zonder een server te benchen, maar kan ook samen met een benchmark starten waarbij resultaten per concurrency1 grafisch worden weergegeven in lijsten en grafieken. In het hoofdstuk ‘Monitoring’ komt dit alles uitgebreid aan bod.
Resultaten De resultaten van een benchmark zijn natuurlijk zeer belangrijk. Hieruit kan dan uitgemaakt worden waar de eventuele bottleneck is. Als ze tegenvallen kan dit door iets kleins zijn als iets dat niet of verkeerd ingesteld is. De monitorresultaten zijn ook belangrijk, zo kunt u bijvoorbeeld zien hoeveel stroom een server verbruikt onder maximale belasting en kan bepaald worden of er eventueel een ander toestel in de plaats moet komen.
Build environement Taal APUS zelf is geschreven in C# omdat deze populair is in de industrie en in MCT programmeren ook wordt gegeven in deze taal.
1
Aantal simultane gebruikers.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
17
Wat het voor de opvolgers een stuk gemakkelijker maakt om de code te interpreteren. Voor APUS SMT werd C++ gekozen omdat deze taal zeer performant is en die zowel op Linux als Windows mits wat aanpassingen zonder problemen kan uitvoeren.
Ontwikkelingspakket APUS en APUS SMT Windows zijn ontwikkeld in Microsoft Visual Studio 2005 omdat die al vertrouwd is van de lessen programmeren en webtechnologie en naar onze bevindingen het beste wat er op de markt te vinden is. APUS SMT Linux werd ontwikkeld in NetBeans wat ook wel een vrij goede en gratis tool is. Het is wel een stuk trager dan Visual Studio, omdat deze in Java geschreven is, en de mogelijkheden iets beperkter zijn. Zo zijn er bijvoorbeeld nergens watches1 te bekennen wat handig is bij het debuggen.
SharpDevelop add-in tree architecture Inleiding Uit het standpunt dat uitbreidbaarheid van APUS zo eenvoudig mogelijk moest zijn werd deze gebouwd steunend op het add-in tree model van SharpDevelop. Het best kunt u dit vergelijken met een geavanceerd plug-in systeem. In ieder project dient er een ‘.addin’ bestandje geplaatst te worden, deze is niets meer dan een Xml bestand. Apus.Core, die een aangepaste versie van de SharpDevelop Core Module is (http://icsharpcode.net/OpenSource/SD/Default.aspx), zorgt voor het interpreteren van deze bestandjes bij het starten van APUS. In APUS is het mogelijk om add-ins in- en uit te schakelen, samen met afhankelijke add-ins, indien deze niet essentieel zijn.
1
Een weergave waarmee kan gekeken worden welke data in een bepaald object zit.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
18
Figuur 4: APUS Add-in Manager
Add-in bestanden Deze manier van werken zal nu vrij bondig uitgelegd worden, meer informatie kunt u vinden op http://www.icsharpcode.net/TechNotes/
>" copyright = "<<>>" description = "<<>>"> <Manifest> >" version = "<<>>" />
AddIn
coreAddin Het coreAddin attribuut wordt gebruikt om aan te duiden dat een module absoluut noodzakelijk is voor de correcte werking van het programma.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
19
Indien deze eigenschap op ‘false’ staat zal de module nog altijd ingeladen worden,maar beschikt de gebruiker om de functionaliteit uit te schakelen via de Add-in manager. Manifest
Het manifest element is verplicht in elk add-in bestand en is verantwoordelijk voor het identificeren van de huidige add-in. Identity
Exact één element van dit type moet toegevoegd worden om een add-in correct te benoemen. De ‘name’ eigenschap is verantwoordelijk voor de interne naamgeving van de module en de ‘version’ eigenschap zal de versie van de module aanduiden. name
Toegelaten waarden: a-z A-Z 0-9. version
In het formaat Major.Minor.Build.Revision. Dependency
Een dependency element is optioneel en kan een oneindig aantal keren voorkomen in het manifest element. addin
De interne naam van de add-in die vereist is voor de correcte werking van deze module. version
Een bepaalde versie of een range van versies die compatibel zijn met de huidige versie van deze add-in. De ‘version’ eigenschap is optioneel. Bijvoorbeeld ‘0.1.0.0-0.2.3.6’ of ‘1.3.0.0’ Versie ‘2.0’ komt overeen met alle versies die beginnen met 2.0 (2.0.*.*) Runtime
Het runtime element is verplicht in elk add-in bestand en is verantwoordelijk voor het koppelen van .NET assemblies aan de add-in bestanden. Import
Dit element zorgt ervoor dat een bepaalde .NET assembly wordt ingeladen wanneer deze add-in wordt aangesproken assembly
Een relatieve of absolute padverwijzing naar een .NET assembly (.dll of .exe)
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
20
Probleemstelling Inleiding In het project waren nog enkele problemen aanwezig die er vorig jaar niet uitgehaald zijn. Hiervan zullen de grootste omschreven worden: degene die te maken hebben met het connectiebeheer.
Connectieprobleem Bij het hebben van afhankelijkheden1 in een actie2 kon het gebeuren dat het programma crashte met de reden dat er te weinig beschikbare connecties naar de server waren. Initieel werd deze bepaald door het dubbele -als pseudo oplossing- van de maximum concurrency. Een voorbeeld om dit te verduidelijken:
ACTIE1 QUERY1 --> openen connectie query1 Bij resultaat… QUERY2 --> openen en sluiten connectie query2 QUERY3 --> openen en sluiten connectie query3 Bij resultaat… QUERY4 --> openen en sluiten connectie query4 --> sluiten connectie query1
Hier ziet u dat er dus drie connecties nodig zijn voor deze actie in plaats van twee, aangereikt in de oplossing van vorig jaar.
Oplossing Connectie aantal correct bepalen Indien er met een datatable (buffered) gewerkt wordt, wordt sowieso al intern de connectie vrijgegeven aan de connectionpool voor hij zijn resultaat zal beginnen lezen, want bij een datatable werkt dit als volgt:
MySqlDataAdapter adapter = new MySqlDataAdapter (command.Command as MySqlCommand); DataSet set = new DataSet (); adapter.Fill (set);
1
Met afhankelijkheden wordt bedoeld dat voor ieder terugkerend resultaat van een query een andere wordt uitgevoerd, die andere is dan de afhankelijke. 2 Een actie is de term die gebruikt wordt waarmee een groep queries, URLs,… bedoeld wordt afgevuurd naar de server. Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
21
adapter.Dispose ();
Bij een datareader (streaming) is dit niet het geval, bij deze is het vereist om een open connectie te blijven hebben tot het einde van de actie. De oplossing nu bestaat er uit dat er per actie per afhankelijkheidsniveau gecontroleerd wordt of er gebruik gemaakt wordt van een datatable of datareader en wordt er per niveau maximaal één extra connectie toegewezen. Het maximum van toegewezen connecties van alle acties wordt dan uiteindelijk gebruikt om de grootte van de connectionpool te bepalen, grootte = maximale concurrency * maximaal toegewezen connecties voor een actie. Code
Dit is een summier overzicht hoe het intern in zijn werk gaat.
// // ---> Bij het genereren van de code. // public AG.Method Convert (string name, OM.CompilationUnit cu) { . . . // // ---> Kijken of er een datareader of datatable wordt gebruikt voor welke query en dit // bijhouden. // CheckExecutionTypes(cu.Statements, 0, 0); . . . }
private void CheckExecutionTypes (List<Apus.QueryScript.DOM.IStatement> statements, int level, int parentIndex) { //Store the variablename of the statement. string declareStatementName = ""; //Store the index of the statement. int index = 0; // // ---> Een object die de index van de eventuele parent bijhoud, de eigen index, hoe diep // die in de structuur zit (niveau) // en of er een datatable of een datareader wordt gebruikt (respectievelijk streaming of // buffered). // StatementIsStreamingOrBuffered streamingOrBuffered = new StatementIsStreamingOrBuffered (); //The list of the next set of statements. List<Apus.QueryScript.DOM.IStatement> subStatements = new List<Apus.QueryScript.DOM.IStatement> (); foreach (OM.IStatement statement in statements) { //Check if it is a declarestatement to store it if the type is streaming. if (statement is OM.DeclareStatement) {
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
22
OM.DeclareStatement declareStatement = (statement as OM.DeclareStatement); //Store the name of the declare statement. if (declareStatement.Variable.Type == OM.VarType.Query) declareStatementName = declareStatement.Variable.Name; } else if (statement is OM.AssignStatement) { OM.AssignStatement assignStatement = statement as OM.AssignStatement; //Check the execute expression to know if it is streaming or buffered. OM.IExpression expr = (statement as OM.AssignStatement).ValueExpression; if (expr is OM.ExecuteExpression) { streamingOrBuffered.index = index; index++; streamingOrBuffered.parentIndex = parentIndex; streamingOrBuffered.level = level; if ((expr as OM.ExecuteExpression).Type == Apus.QueryScript.DOM.ExecuteType.Streaming) streamingOrBuffered.streaming = true; else streamingOrBuffered.streaming = false; _statementIsStreamingOrBuffered.Add (declareStatementName, streamingOrBuffered); } } else if (statement is OM.ForEachStatement) { OM.ForEachStatement foreachStatement = statement as OM.ForEachStatement; //Check the substatements also and increase the level. foreach (OM.IStatement subStatement in foreachStatement.Statements) subStatements.Add (subStatement); int passedLevel = level + 1; CheckExecutionTypes (subStatements, passedLevel, streamingOrBuffered.index); } } }
Een wachttijd bij het vragen van een nieuwe connectie De verschillende threads1 zijn niet altijd op hetzelfde ogenblik klaar met het vrijgeven van een connectie aangezien de ene query langer kan duren dan de andere. Hiervoor is een simpele work-a-round bedacht waarbij het principe is dat u een wachttijd kunt opgeven bij het vragen van een nieuwe connectie.
public IPooledConnection RequestConnection (int timeout)
1
Taken die tegelijkertijd worden uitgevoerd.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
23
{ IPooledConnection connection = RequestConnection (); if (connection == null) { // // ---> Er wordt een partiële timeout bepaald, indien hij geen connectie krijgt wacht ie // gedurende die tijd. // Deze wachttijd bepaald dan ook hoeveel keer er opnieuw geprobeerd wordt om een // connectie te verkrijgen. // int partialTimeout = 5; if (timeout < partialTimeout) partialTimeout = timeout; int tries = (int) Math.Round ((double) (timeout / partialTimeout), 0, MidpointRounding.AwayFromZero); int tryCount = 0; while (connection == null) { System.Threading.Thread.Sleep (partialTimeout); // // ---> Als er geen connectie beschikbaar is, krijgt die de waarde null. // connection = RequestConnection (); if (tryCount++ == tries) break; } } return connection; }
Andere problemen De connectionpooling zelf gebeurt met behulp van een wachtrij, als er een nieuwe connectie gemaakt wordt verdwijnt die uit die wachtrij, omgekeerd wordt die er weer aan toegevoegd. Dit werkte naar behoren tot het aantal simultane threads te hoog werd die deze wachtrij aanspraken. Bijgevolg werd er dan een interne fout gegenereerd waardoor altijd een nul werd toegevoegd in plaats van het correcte ID. Om dit op te lossen werd de code die toevoegt of verwijdert aan de wachtrij threadsafe gemaakt, wat betekent dat geen andere thread de wachtrij mag benaderen als die al niet aangesproken wordt.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
24
As Soon As Possible benchmarken Inleiding Zoals in de inleiding van dit document vermeld werd is dit de originele benchmark. Deze werkte al, mits enkele problemen, voor databaseservers en nu is dezelfde test ook al aanwezig voor webservers en socketservers.
Databaseservers Deze is vrij simpel in omgang, u voegt een nieuw ASAP database benchmark project toe aan een nieuwe of bestaande solution, daar voegt u een querystructuur aan toe waar alle acties in terecht komen. Deze acties zijn gemakkelijk te importeren vanuit een log van een databaseserver, dit kan een tekst bestand zijn maar ook bijvoorbeeld een Xml bestand.
Figuur 5: Een databaseserver log importeren stap één
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
25
Figuur 6: Een databaseserver log importeren stap twee
Bij de volgende stap kunt u dan de structuur verder bepalen, zo kunt u queries afhankelijk van elkaar maken en/of groeperen in acties.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
26
Figuur 7: De structuur bepalen
Bij het klikken op ‘Ok’ worden de queries dan geïmporteerd. Niet vergeten een connectie naar de server toe te voegen.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
27
Figuur 8: Het toevoegen van een nieuwe connectie
Dan is het nog een kwestie van de juiste instellingen te maken…
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
28
Figuur 9: De juiste instellingen maken
…en uit te voeren …
Figuur 10: De benchmark starten
…waarna de code gecompileerd wordt. Nu is het enkel kwestie van op de ‘Play’ knop te klikken en te wachten op resultaat. Ook is het mogelijk om een ‘Performance Monitor’ te selecteren, deze wordt nader besproken in het hoofdstuk ‘Monitoring’.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
29
Figuur 11: Het resultaat bij uitvoeren
Code Codegeneratie De code die gegenereerd wordt werd al deels besproken in het hoofdstuk ‘Probleemstelling’. Deze wordt nu in grote lijnen uitgelegd. Om te compileren wordt de statische klasse 'QueryScriptCompilerWrapper' aangesproken, die verwijst dan door naar de klasse die de voor deze benchmark juiste code zal genereren op basis van argument 'benchmarkType'. Het argument 'structure' is dan de structuur die u zelf gemaakt hebt bij het importeren van een databaseserver log.
public static CompilerResult Compile (Structure structure, BenchmarkType benchmarkType) { if (benchmarkType == BenchmarkType.AsSoonAsPossible) return ASAPQueryScriptCompiler.Compile (structure); else if (benchmarkType == BenchmarkType.ContinuousRate) return CRQueryScriptCompiler.Compile (structure); return null; }
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
30
Vervolgens wordt in dit geval de 'ASAPQueryScriptCompiler' klasse gebruikt. Hier wordt voor iedere actie een functie aangemaakt. Ieder van deze functies is aan te spreken via een delegate1.
public static CompilerResult Compile (Structure structure) { . . . foreach (Function function in structure.Functions) { string conformedMethodName = ConformToCSharpName (function.Name); AG.Method method = CompileFunction (conformedMethodName, function, pool); if (method != null) { cls.Methods.Add (method); } else { LoggingService.ErrorFormatted (typeof (ASAPQueryScriptCompiler), "Error compiling function '{0}'.", function.Name); } } . . . return result; }
Benchmarken zelf De delegatelijst van de gegenereerd assembly wordt per concurrency, per precision2 en per run3 door elkaar gegooid en de items in de lijst worden aangesproken op volgende manier:
private object ExecuteThreaded (object state) { BenchmarkFunctionHandler function = state as BenchmarkFunctionHandler; string msg; long time; uint itemsProcessed; string functionName;
1
Een verwijzing naar een functie. Het aantal keer dat de benchmark wordt uitgevoerd om pieken eruit te halen. 3 Het aantal requests / de concurrency, bijvoorbeeld: als hij bezig is aan concurrency vijf en het aantal requests is honderd dan is de run twintig. 2
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
31
uint numErrors = 0; BenchmarkResult result = function.Invoke (out msg, out time, out itemsProcessed, out functionName, out numErrors); // add time to customtime lock (_lock) { _customTime += time; _itemsProcessed += itemsProcessed; return result; } }
Webservers U voegt een nieuw ASAP web http benchmark project toe aan een nieuwe of bestaande solution, daar voegt u een web http structuur aan toe waar alle acties in terecht komen. Deze acties zijn gemakkelijk te importeren vanuit een log van een webserver.
Figuur 12: Een webserver log importeren stap één
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
32
Figuur 13: Een webserver log importeren stap twee
Daarna kunt u de structuur bepalen, merk op dat in tegenstelling tot de querystructures u hier niet items van elkaar afhankelijk kunt maken. Het is immers ook niet de bedoeling dat als een URL wordt afgevuurd er vervolgens als antwoord erop een andere wordt afgevuurd.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
33
Figuur 14: De structuur bepalen
Niet vergeten een connectie toe te voegen.
Figuur 15: Het toevoegen van een nieuwe connectie
De juiste instellingen maken…
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
34
Figuur 16: De juiste instellingen maken
…en uit te voeren …
Figuur 17: De benchmark starten
…waarna de code gecompileerd wordt. Nu is het enkel kwestie van op de ‘Play’ knop te klikken en te wachten op resultaat.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
35
Figuur 18: Het resultaat bij uitvoeren
Code Codegeneratie Om te compileren wordt de statische klasse ‘ConverterWrapper' aangesproken, die verwijst dan door naar de klasse die de voor deze benchmark juiste code zal genereren op basis van argument 'benchmarkType'. Het argument 'structure' is dan de structuur die u zelf gemaakt hebt bij het importeren van een webserver log.
public static CompilerResult Compile (WebHTTPStructureGroup structure, ServerConnection serverconnection, BenchmarkType benchmarkType) { if (benchmarkType == BenchmarkType.AsSoonAsPossible) return ASAPConverter.Compile (structure, serverconnection); else if (benchmarkType == BenchmarkType.ContinuousRate) return CRConverter.Compile (structure, serverconnection); return null; }
Vervolgens wordt in dit geval de 'ASAPConverter' klasse gebruikt. Hier wordt voor iedere actie een functie aangemaakt. Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
36
public static CompilerResult Compile (WebHTTPStructureGroup structure, ServerConnection serverconnection) { . . . foreach (WebHTTPStructure function in structure.Functions) { string conformedMethodName = ConformToCSharpName (function.Name); AG.Method method = CompileFunction (conformedMethodName, function, serverconnection); if (method != null) { cls.Methods.Add (method); ConverterWrapper.FireFunctionCompiled (new FunctionCompileEventArgs (function, "", true)); } else { LoggingService.ErrorFormatted (typeof (ASAPConverter), "Error compiling function '{0}'.", function.Name); ConverterWrapper.FireFunctionCompiled (new FunctionCompileEventArgs (function, "", false)); } } . . . return result; }
Benchmarken zelf Het benchmarken zelf gebeurt intern op volgende manier.
private object ExecuteThreaded (object state) { BenchmarkFunctionHandler function = state as BenchmarkFunctionHandler; string msg; long time; uint urlsProcessed; string functionName; uint numErrors = 0; BenchmarkResult result = function.Invoke (out msg, out time, out urlsProcessed, out functionName, out numErrors); // add time to customtime lock (_lock) { _customTime += time; _urlsProcessed += urlsProcessed; } return result; }
Socketservers Inleiding Een databaseserver of webserver zijn in wezen ook socketservers, maar deze hebben een vastomlijnd protocol met implementatie in verschillende data access libraries zoals bijvoorbeeld ADO.NET. Voor andere socketservers, bijvoorbeeld een MSN server, bestaat het protocol intern wel maar de implementatie is strikt in de client en de server. Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
37
De bedoeling is nu dat u zelf het protocol kunt omschrijven en kunt zeggen hoe het moet verzonden worden en of er al dan niet een antwoord verwacht wordt.
Voorstudie Inleiding De klasse die connecties en datatransfer regelt is de klasse ‘ClientSocket’. Om deze te testen werd er een kleine client en server gemaakt. Het testproces, op zijn eenvoudigst, is als volgt, de client stuurt een tekstueel bericht naar de server, die pauzeert een aantal milliseconden zodat de tijdsmeting geïllustreerd kan worden en stuurt een berichtje terug als teken van ontvangst. Dit werd ook getest met verschillende encoderingen (ASCII, UTF8,…), manieren van versturen (binair, byte array,…) en transfer protocols (TCP, UDP,…). In APUS werd dit dusver geïmplementeerd voor het versturen van strings. Objecten kunnen ook als die volgens SOAP opgebouwd zijn, wat in wezen ook gewoon tekst is.
Figuur 19: De testclient
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
38
Figuur 20: De testsever
De klasse ‘ClientSocket’ Met deze klasse is het mogelijk om eender welke data te versturen met eender welk transfer protocol en encodering. Het is ook mogelijk om mee te geven of u een antwoord verwacht of niet.
// // --> data: te versturen data. // --> sendType: binair, byte array, SOAP of textueel. // --> encoding: ASCII,UTF8,… enkel nuttig voor textueel of SOAP, wat ook een string is, // versturen. // --> direct: of er een antwoord verwacht wordt of niet. // public void Send (object data, SendType sendType, Encoding encoding, bool direct) { . . . }
Indien er een antwoord verwacht wordt, wordt gewacht tot alle bytes ontvangen zijn. Dit resultaat wordt niet geïnterpreteerd omdat die van geen enkel nut is bij het benchmarken.
private void Receive () { try { _buffer = new byte[_socket.ReceiveBufferSize]; int bytesRead = _socket.ReceiveFrom (_buffer, _receiveSocketFlags, ref _remoteEP); } catch (Exception ex) {
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
39
throw ex; } }
Hoe gebruiken U voegt een nieuw ASAP socket benchmark project toe aan een nieuwe of bestaande solution, daar voegt u een socketstructuur aan toe waar alle acties in terecht komen.
Figuur 21: Een socketserver log importeren stap één
Figuur 22: Een socketserver log importeren stap twee
Daarna kunt u de structuur bepalen.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
40
Figuur 23: De structuur bepalen
Niet vergeten een connectie toe te voegen.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
41
Figuur 24: Het toevoegen van een nieuwe connectie
De juiste instellingen maken…
Figuur 25: De juiste instellingen maken
…en uit te voeren.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
42
Figuur 26: De benchmark starten
Waarna de code gecompileerd wordt en u het onderstaande te zien krijgt. Nu is het enkel kwestie van op de ‘Play’ knop te klikken en te wachten op resultaat.
Figuur 27: Het resultaat bij uitvoeren
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
43
Code Codegeneratie Om te compileren wordt de statische klasse ‘ConverterWrapper' aangesproken, die verwijst dan door naar de klasse die de voor deze benchmark juiste code zal genereren op basis van argument 'benchmarkType'. Het argument 'structure' is dan de structuur die u zelf gemaakt hebt bij het importeren van een socketserver log.
public static CompilerResult Compile (SocketStructureGroup structure, SocketConnection socketconnection, BenchmarkType benchmarkType) { if (benchmarkType == BenchmarkType.AsSoonAsPossible) return ASAPConverter.Compile (structure, socketconnection); else if (benchmarkType == BenchmarkType.ContinuousRate) return CRConverter.Compile (structure, socketconnection); return null; }
Vervolgens wordt in dit geval de 'ASAPConverter' klasse gebruikt. Hier wordt voor iedere actie een functie aangemaakt.
public static CompilerResult Compile (SocketStructureGroup structure, SocketConnection socketconnection) { . . . foreach (SocketStructure function in structure.Functions) { string conformedMethodName = ConformToCSharpName (function.Name); AG.Method method = CompileFunction (conformedMethodName, function, socketconnection); if (method != null) { cls.Methods.Add (method); ConverterWrapper.FireFunctionCompiled (new FunctionCompileEventArgs (function, "", true)); } else { LoggingService.ErrorFormatted (typeof (ASAPConverter), "Error compiling function '{0}'.", function.Name); ConverterWrapper.FireFunctionCompiled (new FunctionCompileEventArgs (function, "", false)); } } . . . return result; }
Benchmarken zelf Het benchmarken zelf gebeurt intern op volgende manier.
private object ExecuteThreaded (object state) { BenchmarkFunctionHandler function = state as BenchmarkFunctionHandler; string msg; long time;
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
44
uint requestsProcessed; string functionName; uint numErrors = 0; BenchmarkResult result = function.Invoke (out msg, out time, out requestsProcessed, out functionName, out numErrors); // add time to customtime lock (_lock) { _customTime += time; _requestsProcessed += requestsProcessed; } return result; }
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
45
Continuous Rate benchmarken Inleiding Deze is analoog aan de ASAP benchmark wat de gebruikersinterface betreft. Op dezelfde manier worden projecten aangemaakt en logs geïmporteerd. Dit zal bijgevolg niet opnieuw besproken worden. De instellingen die u in deze projecten doet zijn iets anders aangezien er een wachttijd tussen de verschillende requests kan ingesteld worden om zo gebruikers realistisch te simuleren. Bijvoorbeeld: Gemiddeld om de twee seconden klikt een gebruiker op een link in een website. De requests worden dan in sets verdeeld die willekeurig bepaald worden per run tussen een minimum en een maximum. Bijgevolg kunnen de wachttijden ook zo worden ingesteld. Net zoals bij de ASAP benchmark krijgt u een soortgelijke feedback terug, per concurrency kunt u dan nog eens de details bekijken.
Figuur 28: Het resultaat bij uitvoeren met details Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
46
Databaseservers Code Codegeneratie Om te compileren wordt de statische klasse 'QueryScriptCompilerWrapper' aangesproken, die verwijst dan door naar de klasse die de voor deze benchmark juiste code zal genereren op basis van argument 'benchmarkType'. Het argument 'structure' is dan de structuur die u zelf gemaakt hebt bij het importeren van een databaseserver log.
public static CompilerResult Compile (Structure structure, BenchmarkType benchmarkType) { if (benchmarkType == BenchmarkType.AsSoonAsPossible) return ASAPQueryScriptCompiler.Compile (structure); else if (benchmarkType == BenchmarkType.ContinuousRate) return CRQueryScriptCompiler.Compile (structure); return null; }
Vervolgens wordt in dit geval de 'CRQueryScriptCompiler' klasse gebruikt. Een groot verschil met de ASAP gegenereerde code is dat de items worden opgesplit in verschillende functies in plaats van voor één actie één functie.
public static CompilerResult Compile (Structure structure) { . . . List
splittedFunctions = GetFunctionsSplittedToItemLevel (structure.Functions); cls.Constructors.Add (CreateConstructor (structure, splittedFunctions, className)); AG.Method method = null; foreach (Function function in splittedFunctions) { string conformedMethodName = ConformToCSharpName (function.Name); method = CompileFunction (conformedMethodName, function, pool); } . . . }
Benchmarken zelf Het benchmarken zelf gebeurt intern op volgende manier.
private object ExecuteSetThreaded (object state) { // // ---> Hoe lang het duurde om deze code uit te voeren wordt ook bewaard, zodat er correct // wordt gewacht om de volgende set van items uit te voeren. // Deze wordt uitgedrukt in ticks en niet in nanoseconds, want de tijd dat een thread moet // 'slapen' wordt toch uitgedrukt in milliseconden, dus dit is meer dan genoeg. // long codeExecutionTime = 0;
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
47
// // ---> Dit voert de correcte item uit die in de gegenereerde code staat. // BenchmarkItemHandler item = null; //Out objects for the invoked itemdelegate. string msg; long time; uint itemsProcessed; string itemName; uint numErrors = 0; List setTime = new List (); Random r = new Random (); int[] valuesToPass = (int[]) state; // // ---> Het bepalen van de tijdspanne voor iedere set van items en het aantal items in die // set. // int randomItems = r.Next (_minimumItemsPerTimespan, _maximumItemsPerTimespan); int randomTime = r.Next(_minimumTimespan, _maximumTimespan); //To store the results for each item executed. List results = new List (); //To control if the number of executed items and the time to process are not exceeded. int minusIndex = 0; long totalProcessTime = 0; string combinedItemName = ""; codeExecutionTime += (DateTime.Now.Ticks - codeStartTime); // // ---> Alle acties worden overlopen. // for (int i = 0; i < (int)valuesToPass.GetValue(3); i++) { item = _dynamicBenchmark[i] as BenchmarkItemHandler; // // ---> Het item wordt uitgevoerd, enkele gegevens -zoals de tijd dat het uitvoeren duurde// worden opgeslaan. // results.Add(item.Invoke (out msg, out time, out itemsProcessed, out itemName, out numErrors)); //Threadsafety lock (_lock) { codeStartTime = DateTime.Now.Ticks; _itemsProcessed += itemsProcessed; //Get the total process time. totalProcessTime += time; _customTime += time; combinedItemName += itemName + "&"; DetermineFastestSlowestItem (itemName, time); // // ---> Controleren of de laatste set van uit te voeren items niet groter is dan het aantal // beschikbare items min de al uitgevoerde items. // if (i + 1 == (int) valuesToPass.GetValue (3)) randomItems = i + 1 - minusIndex; codeExecutionTime += (DateTime.Now.Ticks - codeStartTime); // // ---> Als de set verwerkt is... // if (i + 1 - minusIndex == randomItems) { codeStartTime = DateTime.Now.Ticks; //All the sets processed. _setsProcessed++; combinedItemName = combinedItemName.Substring (0, combinedItemName.Length - 1); //Average, slowest and fastest set. DetermineSlowestFastestAverageSet (combinedItemName, totalProcessTime); //The time left is the randomTime minus the totalProcessTime. double sleeptime = (double) ((randomTime * 10000) - totalProcessTime);
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
48
//Checks the items that are not responded to in time. int notRespondedInTime = 0; codeExecutionTime += (DateTime.Now.Ticks - codeStartTime); // // ---> ... wordt er eventueel even gewacht om de volgende set uit te voeren, indien er // niet gewacht wordt betekent dit dat er één of meerdere items niet op tijd verwerkt // geweest zijn. // if (sleeptime > 0) { _sleepTime += sleeptime; sleeptime -= (double) codeExecutionTime; if (sleeptime > 0) { System.Threading.Thread.Sleep ((int) Math.Round (sleeptime, 0) / 10000); } } else { //If the sleeptime is negative, it means that totalProcessTime is bigger than randomTime. long totalTimeInSet = 0; foreach (long timeInSet in setTime) { totalTimeInSet += timeInSet; if (totalTimeInSet > (randomTime * 10000)) notRespondedInTime += 1; } _notRespondedInTime += (uint) notRespondedInTime; } // // ---> Een detailopname van de set wordt ook bijgehouden. // _lBenchmarkResultsPerTimespan.Add (new CRBenchmarkResultsPerTimespan (randomTime * 10000, totalProcessTime, randomItems, notRespondedInTime, (int) valuesToPass.GetValue (0) + 1, (int) valuesToPass.GetValue (2) + 1, (int) valuesToPass.GetValue (1) + 1)); Debug.Assert (true, "Time : " + totalProcessTime); //Determine the index to check how many items yet got to be processed. //Not needed if at end of the items. if (i + 1 < (int) valuesToPass.GetValue (3)) { minusIndex = i + 1; //Redetermine randomItems and randomTime for a new set of items. randomItems = r.Next (_minimumItemsPerTimespan, _maximumItemsPerTimespan); randomTime = r.Next (_minimumTimespan, _maximumTimespan); //Reset the total process time and the itemName. totalProcessTime = 0; combinedItemName = ""; codeExecutionTime = 0; List setTime = new List (); } } } if (results[results.Count - 1] == BenchmarkResult.Error) OnError (new ErrorEventArgs (msg, numErrors)); } return results; }
Webservers Code Codegeneratie Om te compileren wordt de statische klasse 'ConverterWrapper' aangesproken, die verwijst dan door naar de klasse die de voor deze Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
49
benchmark juiste code zal genereren op basis van argument 'benchmarkType'. Het argument 'structure' is dan de structuur die u zelf gemaakt hebt bij het importeren van een webserver log.
public static CompilerResult Compile (WebHTTPStructureGroup structure, ServerConnection serverconnection, BenchmarkType benchmarkType) { if (benchmarkType == BenchmarkType.AsSoonAsPossible) return ASAPConverter.Compile (structure, serverconnection); else if (benchmarkType == BenchmarkType.ContinuousRate) return CRConverter.Compile (structure, serverconnection); return null; }
Vervolgens wordt in dit geval de 'CRConverter' klasse gebruikt. Een groot verschil met de ASAP gegenereerde code is dat de items worden opgesplit in verschillende functies in plaats van voor één actie één functie.
public static CompilerResult Compile (WebHTTPStructureGroup structure, ServerConnection serverconnection) { . . . int i = 0; AG.Method method = null; foreach (WebHTTPStructure function in structure.Functions) { i = 0; method = null; foreach (Url item in function.Functions) { string conformedMethodName = ConformToCSharpName (function.Name + "_Item" + i++); method = CompileFunction (conformedMethodName, item, serverconnection); if (method != null) cls.Methods.Add (method); else break; } } . . . return result; }
Benchmarken zelf Het benchmarken zelf gebeurt intern op volgende manier:
private object ExecuteSetThreaded (object state) { // // ---> Hoe lang het duurde om deze code uit te voeren wordt ook bewaard, zodat er correct // wordt gewacht om de volgende set van items uit te voeren. // Deze wordt uitgedrukt in ticks en niet in nanoseconds, want de tijd dat een thread moet // 'slapen' wordt toch uitgedrukt in milliseconden, dus dit is meer dan genoeg. // long codeExecutionTime = 0;
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
50
long codeStartTime = DateTime.Now.Ticks; // // ---> Dit voert de correcte item uit die in de gegenereerde code staat. // BenchmarkItemHandler item = null; //Out objects for the invoked functiondelegate. string msg; long time; uint urlsProcessed; string itemName; uint numErrors = 0; List setTime = new List (); Random r = new Random (); int[] valuesToPass = (int[]) state; // // ---> Het bepalen van de tijdspanne voor iedere set van items en het aantal items in die // set. // int randomItems = r.Next (_minimumUrlsPerTimespan, _maximumUrlsPerTimespan + 1); int randomTime = r.Next (_minimumTimespan, _maximumTimespan + 1); //To store the results for each function executed. List results = new List (); //To control if the number of executed items and the time to process are not exceeded. int minusIndex = 0; long totalProcessTime = 0; string combinedItemName = ""; codeExecutionTime += (DateTime.Now.Ticks - codeStartTime); // // ---> Alle acties worden overlopen. // for (int i = 0; i < (int) valuesToPass.GetValue (3); i++) { item = _dynamicBenchmark[i] as BenchmarkItemHandler; // // ---> Het item wordt uitgevoerd, enkele gegevens -zoals de tijd dat het uitvoeren duurde// worden opgeslaan. // results.Add (item.Invoke (out msg, out time, out urlsProcessed, out itemName, out numErrors)); //Threadsafety lock (_lock) { codeStartTime = DateTime.Now.Ticks; _urlsProcessed += urlsProcessed; //Get the total process time. totalProcessTime += time; _customTime += time; combinedItemName += itemName + "&"; setTime.Add (time); DetermineFastestSlowestItem (itemName, time); // // ---> Controleren of de laatste set van uit te voeren items niet groter is dan het aantal // beschikbare items min de al uitgevoerde items. // if (i + 1 == (int) valuesToPass.GetValue (3)) randomItems = i + 1 - minusIndex; codeExecutionTime += (DateTime.Now.Ticks - codeStartTime); // // ---> Als de set verwerkt is... // if (i + 1 - minusIndex == randomItems) { codeStartTime = DateTime.Now.Ticks; //All the sets processed. _setsProcessed++; combinedItemName = combinedItemName.Substring (0, combinedItemName.Length - 1); //Average, slowest and fastest set. DetermineSlowestFastestAverageSet (combinedItemName, totalProcessTime);
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
51
//The time left is the randomTime minus the totalProcessTime. double sleeptime = (double) ((randomTime * 10000) - totalProcessTime); //Checks the functions that are not responded to in time. int notRespondedInTime = 0; _totalRandomTime += randomTime; codeExecutionTime += (DateTime.Now.Ticks - codeStartTime); // // ---> ... wordt er eventueel even gewacht om de volgende set uit te voeren, indien er // niet gewacht wordt betekent dit dat er één of meerdere items niet op tijd verwerkt // geweest zijn. // if (sleeptime > 0) { _sleepTime += sleeptime; sleeptime -= (double) codeExecutionTime; if (sleeptime > 0) { System.Threading.Thread.Sleep ((int) Math.Round (sleeptime, 0) / 10000); } } else { //If the sleeptime is negative, it means that totalProcessTime is bigger than randomTime. long totalTimeInSet = 0; foreach (long timeInSet in setTime) { totalTimeInSet += timeInSet; if (totalTimeInSet > (randomTime * 10000)) notRespondedInTime += 1; } _notRespondedInTime += (uint) notRespondedInTime; } // // ---> Een detailopname van de set wordt ook bijgehouden. // _lBenchmarkResultsPerTimespan.Add (new CRHttpBenchmarkResultsPerTimespan (DateTime.Now.Ticks - randomTime * 10000, randomTime * 10000, totalProcessTime, randomItems, notRespondedInTime, (int) valuesToPass.GetValue (0) + 1, (int) valuesToPass.GetValue (2) + 1, (int) valuesToPass.GetValue (1) + 1)); Debug.Assert (true, "Time : " + totalProcessTime); //Determine the index to check how many items yet got to be processed. //Not needed if at end of the functions. if (i + 1 < (int) valuesToPass.GetValue (3)) { minusIndex = i + 1; //Redetermine randomItems and randomTime for a new set of items. randomItems = r.Next (_minimumUrlsPerTimespan, _maximumUrlsPerTimespan); randomTime = r.Next (_minimumTimespan, _maximumTimespan); //Reset the total process time and the functionName. totalProcessTime = 0; combinedItemName = ""; codeExecutionTime = 0; setTime = new List (); } } } if (results[results.Count - 1] == BenchmarkResult.Error) OnError (new ErrorEventArgs (msg, numErrors)); } return results; }
Socketservers
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
52
Code Codegeneratie Om te compileren wordt de statische klasse 'ConverterWrapper' aangesproken, die verwijst dan door naar de klasse die de voor deze benchmark juiste code zal genereren op basis van argument 'benchmarkType'. Het argument 'structure' is dan de structuur die u zelf gemaakt hebt bij het importeren van een socketserver log.
public static CompilerResult Compile (SocketStructureGroup structure, SocketConnection socketconnection, BenchmarkType benchmarkType) { if (benchmarkType == BenchmarkType.AsSoonAsPossible) return ASAPConverter.Compile (structure, socketconnection); else if (benchmarkType == BenchmarkType.ContinuousRate) return CRConverter.Compile (structure, socketconnection); return null; }
Vervolgens wordt in dit geval de 'CRConverter' klasse gebruikt. Een groot verschil met de ASAP gegenereerde code is dat de items worden opgesplit in verschillende functies in plaats van voor één actie één functie.
public static CompilerResult Compile (SocketStructureGroup structure, SocketConnection socketconnection) { . . . int i = 0; AG.Method method = null; foreach (SocketStructure function in structure.Functions) { i = 0; method = null; foreach (SocketRequest item in function.Functions) { string conformedMethodName = ConformToCSharpName (function.Name + "_Item" + i++); method = CompileFunction (conformedMethodName, item, socketconnection); if (method != null) cls.Methods.Add (method); else break; } } . . . return result; }
Benchmarken zelf Het benchmarken zelf gebeurt intern op volgende manier.
private object ExecuteSetThreaded (object state) { // // ---> Dit voert de correcte item uit die in de gegenereerde code staat. //
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
53
long codeExecutionTime = 0; long codeStartTime = DateTime.Now.Ticks; //Function to invoke, executes statements. BenchmarkItemHandler item = null; //Out objects for the invoked functiondelegate. string msg; long time; uint itemsProcessed; string itemName; uint numErrors = 0; List setTime = new List (); Random r = new Random (); int[] valuesToPass = (int[]) state; // // ---> Het bepalen van de tijdspanne voor iedere set van items en het aantal items in die // set. // int randomItems = r.Next (_minimumRequestsPerTimespan, _maximumRequestsPerTimespan + 1); int randomTime = r.Next (_minimumTimespan, _maximumTimespan + 1); //To store the results for each function executed. List results = new List (); //To control if the number of executed items and the time to process are not exceeded. int minusIndex = 0; long totalProcessTime = 0; string combinedItemName = ""; codeExecutionTime += (DateTime.Now.Ticks - codeStartTime); // // ---> Alle acties worden overlopen. // for (int i = 0; i < (int) valuesToPass.GetValue (3); i++) { item = _dynamicBenchmark[i] as BenchmarkItemHandler; // // ---> Het item wordt uitgevoerd, enkele gegevens -zoals de tijd dat het uitvoeren duurde// worden opgeslaan. // results.Add (item.Invoke (out msg, out time, out itemsProcessed, out itemName, out numErrors)); //Threadsafety lock (_lock) { codeStartTime = DateTime.Now.Ticks; _requestsProcessed += itemsProcessed; //Get the total process time. totalProcessTime += time; _customTime += time; combinedItemName += itemName + "&"; setTime.Add (time); DetermineFastestSlowestItem (itemName, time); // // ---> Controleren of de laatste set van uit te voeren items niet groter is dan het aantal // beschikbare items min de al uitgevoerde items. // if (i + 1 == (int) valuesToPass.GetValue (3)) randomItems = i + 1 - minusIndex; codeExecutionTime += (DateTime.Now.Ticks - codeStartTime); // // ---> Als de set verwerkt is... // if (i + 1 - minusIndex == randomItems) { codeStartTime = DateTime.Now.Ticks; //All the sets processed. _setsProcessed++; combinedItemName = combinedItemName.Substring (0, combinedItemName.Length 1); //Average, slowest and fastest set. DetermineSlowestFastestAverageSet (combinedItemName, totalProcessTime); //The time left is the randomTime minus the totalProcessTime.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
54
double sleeptime = (double) ((randomTime * 10000) - totalProcessTime); //Checks the functions that are not responded to in time. int notRespondedInTime = 0; _totalRandomTime += randomTime; codeExecutionTime += (DateTime.Now.Ticks - codeStartTime); // // ---> ... wordt er eventueel even gewacht om de volgende set uit te voeren, indien er // niet gewacht wordt betekent dit dat er één of meerdere items niet op tijd verwerkt // geweest zijn. // if (sleeptime > 0) { _sleepTime += sleeptime; sleeptime -= (double) codeExecutionTime; if (sleeptime > 0) System.Threading.Thread.Sleep ((int) Math.Round (sleeptime, 0) / 10000); } else { //If the sleeptime is negative, it means that totalProcessTime is bigger than randomTime. long totalTimeInSet = 0; foreach (long timeInSet in setTime) { totalTimeInSet += timeInSet; if (totalTimeInSet > (randomTime * 10000)) notRespondedInTime += 1; } _notRespondedInTime += (uint) notRespondedInTime; } // // ---> Een detailopname van de set wordt ook bijgehouden. // _lBenchmarkResultsPerTimespan.Add ( new CRBenchmarkResultsPerTimespan (DateTime.Now.Ticks - randomTime * 10000, randomTime * 10000, totalProcessTime, randomItems, notRespondedInTime, (int) valuesToPass.GetValue (0) + 1, (int) valuesToPass.GetValue (2) + 1, (int) valuesToPass.GetValue (1) + 1)); //Debug.Assert (true, "Time : " + totalProcessTime); //Determine the index to check how many items yet got to be processed. //Not needed if at end of the functions. if (i + 1 < (int) valuesToPass.GetValue (3)) { minusIndex = i + 1; //Redetermine randomItems and randomTime for a new set of items. randomItems = r.Next (_minimumRequestsPerTimespan, _maximumRequestsPerTimespan); randomTime = r.Next (_minimumTimespan, _maximumTimespan); //Reset the total process time and the functionName. totalProcessTime = 0; combinedItemName = ""; codeExecutionTime = 0; setTime = new List (); } } } // TODO: do this when the result is passed to caller function. if (results[results.Count - 1] == BenchmarkResult.Error) OnError (new ErrorEventArgs (msg, numErrors)); } return results; }
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
55
Monitoring Lokaal De juistheid van een benchmark kan afhangen van verschillende factoren. Zo is het dat de machine waarmee u met ‘APUS’ een server bencht de bottleneck kan zijn. Als de eigen CPU te zwaar belast wordt zal hij intern zelf wachten om nieuwe threads te starten. Zolang die onder of rond de zestig procent blijft is dit geen probleem.
Figuur 29: Een ‘Performance Monitor’ van het lokale toestel
Een ander machine: servermonitoring Inleiding Servermonitoring moest mogelijk zijn om zo te kunnen zien welke invloed belasting heeft op onder andere CPU gebruik, geheugen gebruik, energieverbruik,... Zo kunt u zien bij bijvoorbeeld 200 gebruikers die simultaan een databaseserver aanspreken hoe zwaar die belast wordt, wat door middel van een benchmark handig te simuleren is. Ook is het mogelijk om diepere info van een server op te vragen, zoals het operating system, welke CPU 's erin zitten, diskinfo, .... Om dit alles mogelijk te maken werd het APUS Performance Monitoring Protocol ontwikkeld.
APUS Performance Monitoring Protocol Inleiding Het transfer protocol is TCP. Op het einde van iedere stream moet een '\n'. De te versturen tekst zelf dient ASCII gecodeerd te zijn. Serverconfiguratie instellen Sleutelwoorden SCF; SLEEP; LOGGING;
Resultaat Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
56
SLEEP Om de 'slaaptijd' -in milliseconden- in te stellen aan de kant van de server of hoe lang het moet duren eer dat die zijn antwoord terugzend. Deze wordt aan de serverkant ingesteld omdat bepaalde info opvragen zoals stroommeting een bepaalde wachttijd vereisen. Voorbeeld: SCF;SLEEP;1000;\n
LOGGGING Om logging aan de kant van de server aan of uit te zetten. Voorbeeld: SCF;LOGGING;true;\n
Serverconfiguratie opvragen Sleutelwoorden RQ;SCF; SLEEP; MINSLEEP LOGGING;
Resultaat (teruggekregen data)
SLEEP Hiermee krijgt u de al eerder ingestelde of standaard 'slaaptijd' terug. Voorbeeld: RS;SCF;SLEEP;1000;\n
SLEEPMIN Hiermee krijgt u de minimum 'slaaptijd' terug. Voorbeeld: RS;SCF;SLEEPMIN;200;\n
LOGGGING Zo ziet u of het loggen aan de kant van de server aan of uit staat. Voorbeeld: RS;SCF;LOGGING;true;\n
Ruwe info Sleutelwoorden
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
57
RQ;RI; CPU; DISK; MEM; NET; POWER;
Resultaat (teruggegeven data)
Deze wordt weergegeven onder de vorm “RS;RI;>>>>...;\n”. Bij “RI” weet Apus dat het over ruwe info gaat en dat die in grafiekjes moet worden weergegeven. De rol van “” is enkel die van rootnode. Het vlak waar er op getekend wordt is de “graphCollection” en de grafieken zelf de “graphs”. Naargelang het aantal van beide parameters worden er meer of minder grafieken dynamisch op het scherm weergegeven. De waarde “max” dient dan weer om iedere grafiek afzonderlijk te kunnen laten schalen, indien deze de waarde “Null” heeft wordt geschaald naargelang de maximum meegegeven “value”. “unit” dan weer is in welke eenheid de waardes worden uitgedrukt. Voorbeeld: RS;RI; <max>100 54 Kb/sec <max>100 54 Kb/sec ... <max>0 54 Kb/sec <max>0 54 Kb/sec ... ... ;\n
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
58
Gedetaileerde info Sleutelwoorden RS;DI; AV; OS; CPU; MEM; NET;
Resultaat (teruggegeven data)
Deze is onder de vorm “RS;DI;<serverInfo>......;\n”. “<serverInfo>” dient enkel als rootnode. Wat er wordt meegegeven maakt niet zoveel uit zolang het een correcte Xml is. Voorbeeld: RS;DI; <serverInformation> ... . . . <memInfo> <systemInfo> ;
Andere Sleutelwoorden RQ; WDYH; STOP;
Resultaat
WDYH (what do you have) Hiermee kunt u opvragen welke soort gegevens de server kan opvragen en eventueel loggen. Een omschrijving wordt al dan niet meegegeven. Voorbeeld: RS;WDYH;CPU;<>;...;DISK;<>;...;\n
STOP Om de datatransfer te stoppen en disconnecteren.
Lokaal: De APUS kant Om een nieuwe performance monitor toe te voegen klikt u rechts op een project, kiest u 'Add item' en selecteert u 'Performance Monitors'.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
59
Figuur 30: Een collectie van ‘Performance Monitors’ toevoegen
Om vervolgens een monitor toe te voegen klikt u recht op het item 'Performance Monitors' en kiest u 'Add Performance Monitor'. Daar vult u de naam van de monitor in en de hostname of IP adres van de machine die u wilt monitoren, de poort staat standaard op '2315'. Deze info kan ten alle tijde gewijzigd worden door rechts op de desbetreffende monitor te klikken en 'Edit' te kiezen.
Figuur 31: Een ‘Performance Monitor’ aan de collectie toevoegen
Dubbelklik op de monitor om die te openen. Bij het klikken op de 'Play' knop wordt een connectie gemaakt met de een APUS SMT (wordt later besproken) die op een machine met het ingestelde IP adres staat. Indien er geen connectie kan gemaakt worden wordt u gewaarschuwd.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
60
Figuur 32: Het bericht bij niet kunnen connecteren
Indien er wel een connectie kan gemaakt worden, wordt aan de serverkant opgevraagd welke info hij kan geven (zie het protocol).
Figuur 33: Monitoropties instellen
Na het bepalen wat u wilt hoeft u enkel nog op ‘Start’ te klikken. Automatisch worden er grafieken toegevoegd naargelang welke data er wordt doorgestuurd, wat het monitoren volledig dynamisch maakt.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
61
Figuur 34: De ‘Performance Monitor’
Eenmalige info kan opgevraagd worden door op het info icoontje te klikken.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
62
Figuur 35: Server info opvragen
Monitoren in combinatie met een benchmark U start een nieuwe benchmark en u selecteert een ‘Performance Monitor’.
Figuur 36: Kies een ‘Performance Monitor’
Na het klikken op de ‘Play’ knop wordt u gevraagd te connecteren met een APUS SMT. Merk op dat er twee extra tabbladen beschikbaar zijn met per concurrency informatie over de gemeten waarden. Het monitoren stopt automatisch als de benchmark afgelopen is.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
63
Figuur 37: Monitoren in combinatie met een benchmark
De grafieken kunnen worden opgeslagen als afbeelding, indien gewenst kunt u enkel de gemiddelden of de minima of de maxima laten weergeven.
Server: APUS SMT Inleiding Deze tool is beschikbaar voor zowel het Windows als het Linux platform en is het andere noodzakelijke element om te kunnen monitoren. Dit kan in combinatie met APUS, maar kan ook alleenstaand werken. Het is immers mogelijk om via de commandline ook systeeminfo zoals CPU gebruik op te vragen en dit dan ook te loggen.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
64
Structuur van APUS SMT
Figuur 38: De structuur van APUS SMT
Noot: ‘Taskhandler’ en ‘PerformanceInfoContainer’ verschillen voor de Windows en de Linux client, maar hoofdzakelijk blijft de programmastructuur gelijk. TaskHandler Dit is de klasse die de performance container en de info container uitleest van de ‘PerformanceInfoContainer’ klasse. Communicatie met APUS, logging en weergave op het scherm zijn de voornamelijkste functies van deze klasse. De ‘PerformanceInfoContainer’ klasse communiceert met alle klassen in APUS SMT die data ophalen over het systeem, de data wordt dan op een homogene manier opgeslagen zodat de ‘Taskhandler’ klasse geen rekening meer hoeft te houden met welke data er wordt opgehaald. Dit zorgt er dus voor dat de APUS SMT uitbreidbaar is. Indien er een klasse zou bijkomen hoeft deze enkel gedeclareerd te worden in de ‘PerfomanceInfoContainer’ klasse.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
65
Communicatie met APUS Hiervoor gebruiken we het APUS Performance Monitoring Protocol die we zelf hebben ontworpen. Het idee achter het protocol was dat het de mogelijkheid liet APUS SMT makkelijk te kunnen uitbreiden. StartListening
Deze Functie van de ‘TaskHandler’ klasse wordt opgeroepen vanuit de main. ‘StartListening’ zal een socket creëren en er dan op luisteren voor requests van APUS. Nadat er een request binnenkomt zal deze worden ontleed door de ‘StartListening’ Methode en de nodige functies worden dan ook gestart. Code void TaskHandler::StartListening(){ // listen to sockets oPerfInfoContainer->RefreshPerfData(); cout << "running....\n"; try{ // Create the socket SocketServer in(2315,10); while ( true ){ cout<< "Waiting for new APUS connection\n" ; Socket* new_sock=in.Accept(); cout<< "Socket accepted from APUS\n" ; try{ int tik; tik = 0; string msg; vector <string> dataRecieved; vector <string> dataRecievedWithEnter; bool scfStringOrNot = false ; bool sleepOrNot = false; while ( true ){ tik++; cout<< "waiting for new request \n"; msg = new_sock->ReceiveLine(); cout<< "STRING recieved ="<< msg << " \n"; Split(msg, "\n", dataRecievedWithEnter); FilterBlanksFromVector(dataRecievedWithEnter); for (int l=0;l
WDYH Grafisch
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
66
Figuur 39: WDYH
1. APUS stuurt WDYH (what do you have) naar APUS SMT. 2. De request wordt goed ontvangen op de socket en wordt herkend in de ‘TaskHandler’ klasse. 3. De ‘TaskHandler’ haalt de ‘PerformanceContainer’ op uit de ‘PerformanceInfoContainer’ klasse. 4. Met de ‘PerformanceContainer’ creëert de ‘Taskhandler’ een antwoordt op de vraag van APUS. 5. ‘TaskHandler’ stuurt de string door naar de ‘Socket’ klasse. 6. Het antwoordt wordt verstuurt naar APUS. Code void TaskHandler::AddWhatIHaveToString(ostringstream *s){ *s<<"RS;WDYH;"; for(int i=0;iallPerfInfo.size();i++){ *s<allPerfInfo[i].protName<<";"<allPerfInfo[i].description<<";"; } }
RQ;RI Grafisch
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
67
Figuur 40: RQ;RI
1. APUS vraagt CPU performance info op 2. De request wordt goed ontvangen op de socket en wordt herkend in de ‘TaskHandler’ klasse. 3. De ‘TaskHandler’ haalt de ‘PerformanceContainer’ op uit de ‘PerformanceInfoContainer’ klasse. 4. Met de ‘PerformanceContainer’ creëert de ‘Taskhandler’ een antwoordt op de vraag van APUS. Hij haalt enkel de data over de CPU eruit. 5. ‘TaskHandler’ stuurt de string door naar de ‘Socket’ klasse. 6. Het antwoordt wordt verstuurt naar APUS. Code void TaskHandler::AddWhatIHaveToString(ostringstream *s){ *s<<"RS;WDYH;"; for(int i=0;iallPerfInfo.size();i++){ *s<allPerfInfo[i].protName<<";"<allPerfInfo[i].description<<";"; } }
Logging
Opgehaalde data kan ook gelogd worden naar een ‘comma seperated value’ bestand zodat het makkelijk kan worden geïmporteerd door bijvoorbeeld Excel, OpenOffice, enz.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
68
Figuur 41: Een APUS SMT log
Opstelling van het CSV bestand:
;CPU;MEM;;NET;;;;DISK;;;;;;;; Data and time;cpu1-%;Availabe physical-MB;Availabe Swap-MB;lo Rx-kB/sec;lo Tx-kB/sec;eth0 Rx-kB/sec;eth0 Tx-kB/sec;sda read-kB/sec;sda writekB/sec;sda1 read-kB/sec;sda1 write-kB/sec;sda2 read-kB/sec;sda2 writekB/sec;sda5 read-kB/sec;sda5 write-kB/sec; Fri May 25 09:36:44 2007;0;160;1576;0;0;0;0;0;0;0;0;0;0;0;0; Fri May 25 09:36:44 2007;0;160;1576;0;0;0;0;0;0;0;0;0;0;0;0; . . .
Lijn 1: De spaties zo plaatsen dat u een duidelijker overzicht hebt dat u bijvoorbeeld met CPU data bezig bent. Lijn2: Voor elke kolom een header om specifiek aan te kunnen tonen. Lijn 3: Data. Werking
De ‘TaskHandler’ Klasse gebruikt de performance container van de ‘PerformanceInfoContainer’ klasse. Dan worden alle data objecten geïtereerd in een for lus en de info van elk data object wordt dan weggeschreven naar een tekstbestandje. Eerste lijn: //data and time--------logging<<" ;" ; //leave first item clean so we can pass date and time header in line2 //---------------------for (int i=0;iallPerfInfo.size();i++){ logging<< oComputerPerfContainer->allPerfInfo[i].protName<<";";
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
69
for(int j = 0;j < (oComputerPerfContainer>allPerfInfo[i].valueBox.size()-1);j++){ logging<< ";"; } } logging<<endl;
Eerst laten we een spatie open omdat bij de data voor de eerste kolom de tijd wordt ingevuld. Dan wordt voor elk type object in de hoofdcontainer eerst zijn naam weggeschreven en dan een x aantal spaties, waar x het aantal objecten in de Type object zit min één. Tweede lijn: //data and time--------logging<<"Data and time;"; //---------------------for (int i=0;iallPerfInfo.size();i++){ for(int j=0;j<(oComputerPerfContainer>allPerfInfo[i].valueBox.size());j++){ logging << oComputerPerfContainer->allPerfInfo[i].valueBox[j].name<<""<allPerfInfo[i].unit<<";"; } } logging << endl;
Alle objecten die zich in de container bevinden worden geïtereerd en daarvan enkel naam en de ‘unit’ weggeschreven naar het logbestandje. Zo bekomen kolomkoppen voor de data. Derde lijn: oPerfInfoContainer->RefreshPerfData(); //data and time--------logging<allPerfInfo.size();i++){ for(int j = 0;j<(oComputerPerfContainer>allPerfInfo[i].valueBox.size());j++){ logging<< oComputerPerfContainer>allPerfInfo[i].valueBox[j].value<<";"; } }
Alle objecten overlopen in de container en dan de waarde van het ervan wegschrijven. PerformanceInfoContainer ‘PerformanceInfoContainer’ zorgt voor de communicatie met alle klassen die data ophalen over het systeem. De klasse wordt gebruikt als tussenlaag tussen de ‘Taskhandler en al de klassen die data ophalen. Dit werd gedaan zodat de ‘TaskHandler’ geen rekening moet houden met al de andere klassen behalve met de ‘PerformanceInfoContainer’ klasse. Grafisch
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
70
Figuur 42: De structuur van APUS SMT
1. Bij het opvragen van de performance data moet er een vernieuwing gebeuren 2. In de refresh functie van de ‘PerformanceInfoContainer’ wordt de refresh functie opgeroepen van alle klassen die data ophalen. 3. Voor Windows wordt de ‘WMI’ klasse aangesproken en zo ‘performance data’ opgehaald, voor Linux wordt de ‘/proc’ map gedeeltelijk geparst voor de ‘performance data’ Code void PerformanceInfoContainer::RefreshPerfData(){ computer->refreshStats(); oComputerPerf.allPerfInfo.clear(); FillPerfContainer(); }
De performance container bevat info van het systeem op een bepaald tijdstip. Dus als de ‘RefreshPerfData’ methode wordt aangesproken wordt eerst de container leegemaakt en dan terug gevuld door de ‘FillPerfContainer’ methode aan te roepen. Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
71
void PerformanceInfoContainer::RefreshDetailedInfoData(){ oComputerDetailedInfo.allDetailedInfo.clear(); FillInfoContainer(); }
Hetzelfde geldt voor de info container:
void PerformanceInfoContainer::FillPerfContainer(){ FillPerfContainer_Cpu(); FillPerfContainer_Mem(); FillPerfContainer_Disk(); FillPerfContainer_Net(); }
void PerformanceInfoContainer::FillInfoContainer(){ FillInfoContainer_Os(); FillInfoContainer_Cpu(); FillInfoContainer_Mem(); FillInfoContainer_Net(); FillInfoContainer_Disk(); }
void PerformanceInfoContainer::FillPerfContainer_Net(){ Struct_PerfDataObject oValueContainer; Struct_PerfDataBox oTypeContainer; oTypeContainer.protName ="NET"; oTypeContainer.unit ="KB/sec"; oTypeContainer.description ="Network usage in " + oTypeContainer.unit; for (int i=0; igetNtwInterfaceCount(); i++){ NetworkInterface* ntwInterface = computer->getNtwInterface(i); oValueContainer.name= "Nic" + ToString(i) + " Tx"; oValueContainer.max = "Null"; oValueContainer.min = "Null"; oValueContainer.value = ToString(ntwInterface->getSentBytes()); oTypeContainer.valueBox.push_back(oValueContainer); oValueContainer.name= "Nic" + ToString(i) + " Rx"; oValueContainer.max = "Null"; oValueContainer.min = "Null"; oValueContainer.value = ToString(ntwInterface->getReceivedBytes()); oTypeContainer.valueBox.push_back(oValueContainer); } oComputerPerf.allPerfInfo.push_back(oTypeContainer); }
Uitbreidbaarheid van APUS SMT
Dankzij de ‘PerfromanceInfoContainer’ klasse is het heel makkelijk om APUS SMT uit te breiden met een nieuwe klasse dat bijvoorbeeld data zou ophalen over de snelheid van de CD/DVD speler. Door volgende stappen te volgen: 1. Declareer de klasse in de constructor van de ‘PerformanceInfoContainer’ klasse
PerformanceInfoContainer::PerformanceInfoContainer(){ computer = new Computer();
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
72
oDVD = new DVD(); InitializeTimeSetting(); }
2. Voeg een methode toe aan de ‘FillPerf(/info)Container’ methode bijvoorbeeld ‘FillInfoContainer_CD’
void PerformanceInfoContainer::FillPerfContainer(){ FillPerfContainer_Cpu(); FillPerfContainer_Mem(); FillPerfContainer_Disk(); FillPerfContainer_Net(); FillPerfContainer_DVD(); }
3. In de methode ‘FillInfoContainer_CD’ maakt u gebruik van uw nieuwe klasse en haalt u uw data daar op en voegt u ze toe aan de performance container APUS SMT Gebruiken Tclap
APUS SMT heeft drie functies: - Logging - Communiceren met Apus - Displaying Om te kunnen kiezen tussen de functies die APUS SMT aanbiedt hebben we gedacht aan Tcalp (Templatized C++ Command Line Parser Library ). Dit is een makkelijk te gebruiken bibliotheek die werkt voor Linux en Windows. Zo kan u snel opties toevoegen voor uw applicatie en al de rest zoals de help bijvoorbeeld wordt gegenereerd door de library zelf. U kunt de bronbestanden hiervan afhalen op http://tclap.sourceforge.net/.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
73
Figuur 43: APUS SMT Gebruiken Mogelijke parameters
-m : Maximum grote in MB voor de log bestandjes -p <string>: Seriële poort die gebruikt moet worden om te communiceren met de ‘Extech True RMS Power Analyser’ -f <string>: Filename waar naartoe gelogd moet worden -i : Interval voor wanneer er data moet opgehaald worden. -d : Hoe lang er gelogd moet worden, de standaard waarde is één uur -v: Als u de performantie data op het scherm wilt tonen -s: Start de server, er wordt een socket gecreëerd die wacht op requests van APUS -l: Data loggen naar een CSV bestandje Voorbeeld: ApusSmt –s –p /dev/ttys0 –m 100 Dit zal APUS SMT starten als server die communiceert met de ‘Extech True RMS Power Meter’ over poort ttyS0 en indien APUS logging vraagt dan zal er voor het logbestand een limiet van 100 mb grootte worden ingesteld.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
74
Besluit APUS en APUS SMT zullen zeker nog koppen doen rollen in de toekomst. Nu is al een groot stuk van de doelstelling bereikt, namelijk monitoren en benchmarken. Beide applicaties zijn op punt gesteld, een weergave van resultaten in grafieken is mogelijk en een nieuw type benchmark werd toegevoegd, maar hier stopt het niet. In de toekomst zal het mogelijk zijn om vanuit APUS zelf advies te krijgen welke configuratie/hardware aanpassingen u moet doen aan uw server zodat de eventuele bottleneck opgelost zou zijn of dat het toestel nog performanter zou werken. Incluis advies over hoe de server zuiniger op energie zou kunnen werken. De algemene doelstelling van het Sizing Servers Lab is ook bereikt, want door onze software kon het research team betere feedback geven aan de KMO ‘s waarmee we samenwerkten. Hou uw oren open, want u hoort nog hiervan!
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
75
Conclusies Leandro Cavaliere Ik ben zeer tevreden met APUS SMT, Het is niet enkel een server applicatie die afhankelijk is van APUS, Je kan het ook als een standalone applicatie gebruiken en je monitoring laten wegschrijven naar een ‘comma seperated value’ bestandje. Ook heb ik mij kunnen amuseren tijdens mijn stage, we hadden een leuke groep elke dag was wel lachen, we konden goed met elkaar werken daarom vind ik het spijtig dat er een einde aan komt. Ik ga het sslab echt missen. Uiteindelijk is alles tot een goed einde gekomen, APUS SMT voor Windows en voor Linux werden afgewerkt en getest. Ben hier dan ook fier op, want het is altijd leuk aan iets waar je maanden aan hebt gewerkt om het dan in gebruik te zijn. Na de stage bij sslab heb ik een zicht op hoe het eraan toe gaat in een IT bedrijf, De samenwerking met KMO ’s de gesprekken met grote bedrijven zoals VMWare, IBM, .. en de vergaderingen met Johan Degelas en Brecht Kets. Het was een mooie ervaring waar ik veel van heb bijgeleerd. Met pijn in mijn hart zeg ik vaarwel tegen het sslab en misschien tot over twee jaar ☺.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
76
Dieter Vandroemme Het project waaraan ik werkte was zeer boeiend, maar niet altijd eenvoudig. Ik ben in aanraking gekomen met de ‘SharpDevelop add-in tree architecture’ wat ik verplichte materie vind voor de optie Office Automation. Of om een ander voorbeeld te geven, multithreaded programmeren. In code analyseren ben ik ook een stuk sneller geworden, dit was een noodzaak om de moeilijke problemen in APUS op te lossen. Ook heb ik wat meer inzicht gekregen in serverhardware en besturingssystemen en met enkele databaseservers, zoals Sybase, moeten werken die ik nog niet kende. Maar dit zijn niet de enige vaardigheden die ik opgedaan heb, zo zijn we ook als team met mensen van onder andere VMWare en Intel in contact gekomen waar we een korte presentatie aan moesten geven. Ook waren we te zien op de opendeurdag. En het meest leuke aan deze stage is dat de vruchten van ons werk wel degelijk gebruikt worden en niet ergens in de vergetelheid belanden.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
77
Lijst van afbeeldingen Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur
1: Het Sizing Servers team ............................................................... 7 2: Vergelijking TCP met Sheridan (APUS) ......................................... 13 3: Visie van Sheridan (APUS) .......................................................... 14 4: APUS Add-in Manager ................................................................ 18 5: Een databaseserver log importeren stap één ................................. 24 6: Een databaseserver log importeren stap twee................................ 25 7: De structuur bepalen ................................................................. 26 8: Het toevoegen van een nieuwe connectie...................................... 27 9: De juiste instellingen maken ....................................................... 28 10: De benchmark starten .............................................................. 28 11: Het resultaat bij uitvoeren ........................................................ 29 12: Een webserver log importeren stap één ...................................... 31 13: Een webserver log importeren stap twee..................................... 32 14: De structuur bepalen................................................................ 33 15: Het toevoegen van een nieuwe connectie .................................... 33 16: De juiste instellingen maken ..................................................... 34 17: De benchmark starten .............................................................. 34 18: Het resultaat bij uitvoeren ........................................................ 35 19: De testclient ........................................................................... 37 20: De testsever ........................................................................... 38 21: Een socketserver log importeren stap één ................................... 39 22: Een socketserver log importeren stap twee ................................. 39 23: De structuur bepalen................................................................ 40 24: Het toevoegen van een nieuwe connectie .................................... 41 25: De juiste instellingen maken ..................................................... 41 26: De benchmark starten .............................................................. 42 27: Het resultaat bij uitvoeren ........................................................ 42 28: Het resultaat bij uitvoeren met details ........................................ 45 29: Een ‘Performance Monitor’ van het lokale toestel .......................... 55 30: Een collectie van ‘Performance Monitors’ toevoegen...................... 59 31: Een ‘Performance Monitor’ aan de collectie toevoegen................... 59 32: Het bericht bij niet kunnen connecteren ..................................... 60 33: Monitoropties instellen.............................................................. 60 34: De ‘Performance Monitor’.......................................................... 61 35: Server info opvragen................................................................ 62 36: Kies een ‘Performance Monitor’ .................................................. 62 37: Monitoren in combinatie met een benchmark ............................... 63 38: De structuur van APUS SMT ...................................................... 64 39: WDYH .................................................................................... 66 40: RQ;RI .................................................................................... 67 41: Een APUS SMT log ................................................................... 68 42: De structuur van APUS SMT ...................................................... 70 43: APUS SMT Gebruiken ............................................................... 73
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
78
Bijlagen Projectweken Dieter Vandroemme Inleiding Omdat mijn projectweken ook in het stagebedrijf was werden ook enkele dingen geprogrammeerd die in het verdere verloop van de stage ook werden gebruikt. Dit vond ik belangrijk om ook even te vermelden. Wat ik in die weken gedaan heb staat er wel volledig los van, om een voorbeeld te geven: Een usercontrol moest gemaakt worden om het importeren van queries gemakkelijker te maken en hierbij moest gebruik gemaakt worden van de ‘SharpDevelop add-in tree architecture’. En dit heeft in wezen niks te maken met benchmarken of monitoren. Er diende ook een proof of concept1 gemaakt te worden voor het socketmonitoren, maar die werd al eerder omschreven als vooronderzoek en wordt bijgevolg niet vermeld. Hetgeen u hieronder te lezen krijg is een kopie van de verslaggeving, op onze eigen wiki, over de usercontrol. Iedereen van het Sizing Servers team was verplicht zijn verslagen daarop te plaatsen.
De usercontrol: fase één Inleiding De bedoeling was een algemene control te maken om het bewerken, sorteren, groeperen, ... van items, bijvoorbeeld queries. Met algemeen wordt bedoeld dat deze moet werken voor wat u er maar wilt instoppen, dus ook bijvoorbeeld URLs. In dit artikel wordt de eerste fase behandeld: de control voor abstractie. Wat wil zeggen dat het maar voor één specifiek iets werkt, in dit geval queries.
1
Een bewijs of het in dit geval implementeren van een socketbenchmark wel mogelijk is.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
79
De beginsituatie
Op het eerste zicht niet veel op aan te merken, de functionaliteit reflecteert in de GUI (pijltjes om te verplaatsen of afhankelijk te maken, andere controls om te verwijderen of toe te voegen), maar het werkt niet volledig zoals het moet. U kunt afhankelijkheden instellen en de statementlist genereren, maar daar stopt het. De scrollbar werkte niet, het wisselen van de items ook niet, de afhankelijkheden maar tot op één niveau, het aantal items per pagina instellen ook niet,....
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
80
De eindsituatie
Dit is wat het nu is en qua functionaliteit nog min of meer moet worden. Om even een korte opsomming te maken: Al verwezenlijkt
-
Icoontjes naar gelang, vetjes als een groep Spreiden van de items over verschillende pagina 's Afhankelijkheden tot in niveau oneindig indien gewenst Afhankelijkheden worden gekleurd naargelang hun level van afhankelijkheid
- Wisselen van items, eventuele afhankelijkheden worden mee gewisseld
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
81
- Mogelijkheid tot groeperen - Toevoegen en wijzigen van items - Correcte generatie van de statementlist(alle items, niet alleen die in de huidige pagina) - ... Te verwezenlijken
- Verwijderen en invoegen van items - Meerdere items per keer kunnen selecteren - Fase twee: abstract/add-in based maken Korte toelichting Afhankelijkheden
'Afhankelijkheden' is een term om een item te benoemen dat uitgevoerd wordt indien er een ander item uitgevoerd wordt (afhankelijk van...). Groepen
Groepen zijn niets meer dan een verzameling items die sequentieel kunnen worden uitgevoerd. Statementlist
Voor ieder item in deze lijst wordt een nieuwe treenode gemaakt met daarin voor dit geval een stuk queryscript. Hierin vindt u dan natuurlijk dezelfde structuur terug die u hebt opgegeven(groepen, afhankelijkheden).
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
82
Add-in based
Hiermee wordt bedoeld dat de control in APUS zijn add-in tree wordt gestopt, gebaseerd op de add-in tree architecture van SharpDevelop. Nu weet u daar waarschijnlijk nog niet veel meer mee dus sta me toe dit even verder te verduidelijken. Bij grote projecten is dynamisch kunnen programmeren belangrijk, hoe dynamischer het systeem is hoe gemakkelijker het wordt om snel te ontwikkelen. Een concreet voorbeeld vanuit APUS: Er zou een mogelijkheid moeten zijn om socketservers te benchmarken, nu is het al zo bij databases en webservers. Indien u gewoon lukraak zou programmeren zou u heel wat veranderingen moeten doen. Zoals de mogelijkheid om socketserver benchmark projecten correct weer te geven in de solution treeview en het aanpassen van het menu. Met een dynamish systeem zoals de SharpDevelop add-in tree architecture wordt dit alles veel gemakkelijker. Zo kunt u naargelang welk object zeggen hoe die moet getekend worden, de menu's bepalen, bijpassende dialoogvenstertjes, noem maar op. Eenmaal u dit door hebt is het een vrij eenvoudig systeem. Dit is nu heel summier uitgelegd, maar er komt meer bij kijken. In het volgende artikel wordt er dieper op ingegaan. Indien u meer geïnteresseerd bent kunt u terecht op volgende webpagina: http://www.icsharpcode.net/TechNotes/
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
83
De usercontrol: fase twee Inleiding
Grafisch gezien is er niet veel veranderd, maar qua functionaliteit is dit toch serieus uitgebreid: - Verplaatsen en afhankelijk van maken is geoptimaliseerd - Het groeperen is gewijzigd - Het bepalen van welke (menu)actie er voor een bepaald item mogelijk is (add-in based) - Wijzigen en toevoegen van items ook add-in based - Kopieren en plakken - ... Add-in based ontwikkelen Nu zal ik wat verder ingaan op hoe heel dit systeem in zijn werk gaat aansluitend op het vorige artikel wat specifieke voorbeelden vanuit het project. De add-in tree en add-in bestanden
Deze 'boom' houdt intern bij waar wat staat en is samengesteld uit een aantal add-in bestanden. Per project in de solution wordt er een add-in bestand aangemaakt dat niks meer is dan een xml bestand. Een voorbeeld hiervan:
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
84
--------->>> Auteur, copyright, omschrijving en of het een core add-in is (verplicht voor het programma). --------- <Manifest> --------->>> At runtime de base assembly importeren. --------- --------->>> Doozers: klassen die als tags in een add-in kunnen gebruikt worden met een bepaalde set al dan niet verplichte attributen. >>> Meer uitleg volgende hoofdstuk. --------- --------->>> Een doozer die ik gemaakt heb. Meer uitleg volgende hoofdstuk. --------- --------->>> Enkele conditions bijvoorbeeld om menuitems (on)zichtbaar te zetten als de solution al dan niet actief is of de mogelijkheid om treenodes te hernoemen. --------- --------->>> Toevoegen van enkele services, deze zijn eigen gedefinieerde doozers. ---------<Path name = "/Apus/Services"> <Service id="RecentSolutionService" class = "Apus.Base.Solution.RecentSolutionService" /> <Service id="SolutionService" class = "Apus.Base.Solution.SolutionService" lazyload = "false" /> <Service id="AboutService" class = "Apus.Base.AboutService" /> --------->>> Toevoegen van enkele filefilters, deze zijn doozers die sowieso al in de core aanwezig zijn. >>> ... ---------<Path name = "/Apus/Project/FileFilter">
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
85
<Path name = "/Apus/Solution/FileFilter"> <Path name = "/Apus/Project/Templates/Project"> <Path name = "/Apus/Project/Templates/Item"> <Path name = "/Apus/AddinTreeView/DefaultTreeNodeBuilders"> <Path name = "/Apus/Controls/CodeEditor/ContextMenu"> <MenuItem id = "Cut" label = "Cut" icon = "Icon.16x16.Cut" class = "Apus.Base.Gui.CutCommand" /> <MenuItem id = "Copy" label = "Copy" icon = "Icon.16x16.Copy" class = "Apus.Base.Gui.CopyCommand" /> <MenuItem id = "Paste" label = "Paste" icon = "Icon.16x16.Paste" class = "Apus.Base.Gui.PasteCommand" /> <MenuItem type = "Separator" /> <MenuItem id = "SelectAll" label = "Select All" class = "Apus.Base.Gui.SelectAllCommand" /> <Path name = "/Apus/About/Authors">
Hoe ik dit toegepast heb
Ter opfrissing, de bedoeling van de control is dat gelijk welk object gepreviewed kan worden. Deze objecten kunnen enkele restricties hebben, bijvoorbeeld: Kunnen ze gegroepeerd worden? Of kunnen er nieuwe objecten toegevoegd worden? Als u het object bewerkt, hoe moet het dialoogvenster om dit te doen dan eruit zien? De belangrijkste stappen zullen omschreven worden. Stap 1: Een custom doozer Evengoed zou ik de standaard doozer ‘Class’ kunnen gebruikt hebben, maar ter gebruikersgemak heb ik een doozer gemaakt die exact hetzelfde attribuut heeft als ‘Class’, namelijk ‘class’.
public class PreviewBuilderDoozer : IDoozer { --------->>> Een codon is een object dat evengoed niet programmatorisch gebonden kan zijn, zoals een graphics resource bijvoorbeeld. ---------public object BuildItem (object caller, Codon codon, ArrayList subItems) { return codon.AddIn.CreateObject (codon.Properties["class"]); } public bool HandleConditions
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
86
{ get { return false; } } }
En op deze manier komt die in een add-in bestand:
Stap 2: Een interface die omschrijft wat er kan met een eventuele abstracte builder klasse Abstract
public interface IPreviewBuilder { bool CanBuildObject (Type objectType); bool CanAddNew (); bool CanCopyPaste (); bool CanEdit (); bool CanRemove (); bool CanGroup (); bool CanIndent (); bool CanMove (); AddEditPreviewBase AddEditPreview (); PreviewInputBase GetFromClipboard (); } public abstract class AbstractPreviewBuilder : IPreviewBuilder { --------->>> Simpelgezegd, hier mag niks. ---------#region IPreviewBuilder Members public abstract bool CanBuildObject (Type objectType); public virtual bool CanAddNew () { return false; } public virtual bool CanCopyPaste () { return false; } public virtual bool CanEdit () { return false; } public virtual bool CanRemove () { return false; } public virtual bool CanGroup () { return false; } public virtual bool CanIndent () { return false; } public virtual bool CanMove ()
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
87
{ return false; } public abstract AddEditPreviewBase AddEditPreview (); public abstract PreviewInputBase GetFromClipboard (); #endregion }
Concreet: als u queries dient te previewen
public class SqlStatementsPreviewBuilder : AbstractPreviewBuilder { #region IPreviewBuilder Members --------->>> Kijken of een klasse van het type SqlStatements -een collectie van instanties van SqlStatement- kan gebuild worden (zie verder). ---------public override bool CanBuildObject (Type objectType) { return objectType == typeof (SqlStatements); } public override bool CanAddNew () { return true; } public override bool CanCopyPaste () { return true; } public override bool CanEdit () { return true; } public override bool CanRemove () { return true; } public override bool CanGroup () { return true; } public override bool CanIndent () { return true; } public override bool CanMove () { return true; } --------->>> Hoe de het dialoogvenster er moet uitzien bij het toevoegen of wijzigen van een object. ---------public override AddEditPreviewBase AddEditPreview () { return new AddEditSqlStatement(); } --------->>> Een gekopieerde instantie van SqlStatement uit het clipboard halen. ---------public override PreviewInputBase GetFromClipboard () { SqlStatement statement = null; try { IDataObject od = Clipboard.GetDataObject (); if (od.GetDataPresent (typeof (PreviewInputBase))) statement = od.GetData (typeof (PreviewInputBase)) as SqlStatement;
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
88
} catch (Exception e) { LoggingService.Error (typeof (SqlStatement), "getting data from clipboard failed", e); } return statement; } #endregion }
Op deze manier komt die in een add-in file:
<Path name = "/Apus/Dialogs/Preview/PreviewBuilders">
Stap 3: De objecten previewen en kijken door welke PreviewBuilder ze kunnen worden gebuild, afhankelijk daarvan kunt u bijvoorbeeld geen gepreviewde objecten verwijderen In code:
PreviewBuilder previewBuilder = new PreviewBuilder (); previewBuilder.InitializePreviewBuilderPath("/Apus/Dialogs/Preview/PreviewBu ilders"); foreach (IPreviewBuilder ipb in previewBuilder.PreviewBuilders) { if (ipb.CanBuildObject (input.GetType())) { _previewBuilder = ipb; break; } }
In het object ‘_previewbuilder’ zit dan wat mag en wat niet, welk dialoogvenster bij het wijzigen of toevoegen en wat bij plakken uit het clipboard moet gehaald worden. Slot
Ik vond dit een leerrijk project en zeker een uitdaging. Ik vind het jammer dat dingen zoals de ‘add-in tree architecture’ niet gezien worden in het lessenpakket van Office Automation. Indien u geïnteresseerd bent mag u mij altijd een mailtje sturen.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
89
Projectweken Leandro Cavaliere Inleiding In de projectweken heb ik uitgedokterd hoe er kon gecommuniceerd worden met de ‘Extech True RMS Power Analyser’ om zo aan energie meting te kunnen doen. Zo heb ik ondervonden dat voor de communicatie met de powermeter over de rs232 poort de rts lijn moet uitgeschakeld worden. Hetgeen u hieronder te lezen krijg is een kopie van de verslaggeving, op onze eigen wiki. Iedereen van het Sizing Servers team was verplicht zijn verslagen daarop te plaatsen.
Powermeter Inleiding De bedoeling was om een Linux client te ontwikkelen in C++. Ik heb gebruik gemaakt van Ubuntu met daar Netbeans op. Overzicht
PmConnection // // File: PmConnection.h // Author: leandro // // Created on 6 maart 2007, 10:31 // #ifndef _PmConnection_H #define _PmConnection_H #include #include "ValuePM.h" #include class PmConnection{ public: PmConnection(); ~PmConnection(); char *dechiperRange(int ibyte); double dechiperData(int ibyte1, int ibyte2,int range); vector readPortPm ( int minBytes); vector GetOne(char chartosend , int numberofbytes); void printingvector( vector ddata); void printData (char cfunction, int numberofbytes);
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
90
void void void bool
loggingData(int duur); openPort(); closePort(); isServerReady();
}; #endif
/* _PmConnection_H */
Uitleg van de functies/methodes: - PmConnection() Dit is de constructor. - ~PmConnection() Dit is dan de destructor, deze moet u gebruiken als u het object niet meer gebruikt en het zo dan uit het geheugen wist, doet u dit niet dan kunnen er memory leaks voorkomen. - char *dechiperRange(int ibyte) Eerste databyte aan de functie meegeven, de functie gaat dan controleren over welke range het gaat en returned deze dan in de vorm van een char *. - double dechiperData(int ibyte1, int ibyte2,int range) Drie bytes aan de functie meegeven, hieruit wordt dan de waarde berekend en deze wordt gereturned in de vorm van een double. - vector readPortPm ( int minBytes) Functie die luistert op de seriële poort, als er bytes binnenkomen berekent die dan de range en waarde van elke datablock (vijf bytes) en geeft deze dan terug in de vorm van een vector van ValuePm objecten. - vector GetOne(char chartosend , int numberofbytes) Functie waaraan een char wordt meegeven, chartosend in eigenlijk hetgeen u verstuurt naar het toestel, bv " " (spatie) dan weet het toestel dat hij al zijn data moet terugsturen, in deze functie wordt dan readPortPm aangesproken en zo bekomen we weer een vector van ValuePM objecten die dan teruggegeven worden. - void openPort() Hierin gebeuren alle settings voor de seriële poort (baudrate instellen, stopbit, rts lijn disablen ect..). - void closePort(); Settings die veranderd zijn aan de seriële poort door het programma ongedaan maken. - void loggingData(int duur); Data ophalen van het toestel en deze dan wegschrijven naar een CSV bestandje. ValuePM
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
91
// // File: ValuePM.h // Author: leandro // // Created on 5 maart 2007, 14:14 // #ifndef _ValuePM_H #define _ValuePM_H #include <string> #include <sstream> using namespace std; class ValuePm{ public: ValuePm(double idvalue, char *isortOfValue); ValuePm(); ~ValuePm(); double getValue(); string getSortOfValue(); void setValue( double idvalue); void setSortOfValue(char *isortOfValue); private: double dvalue; char *sortOfValue; }; #endif /* _ValuePM_H */
Een simpele klasse om de waarde en range in een object te kunnen steken. De termios klasse Ik ben begonnen met het aanspreken van de seriële poort in Linux. Hiervoor heb ik de termios klasse gebruikt. Om wat wegwijs te geraken zou u best deze howto eens bekijken op http://www.tldp.org/HOWTO/Serial-Programming-HOWTO/1. Hier hebt u de nodige uitleg over de gebruikte flags in deze klasse: http://www.opengroup.org/onlinepubs/007908799/xsh/termios.h.html2. Praktijk (code uitleg) /* BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed. CRTSCTS : output hardware flow control (only used if the cable has all necessary lines. See sect. 7 of Serial-HOWTO) CS8 : 8n1 (8bit,no parity,1 stopbit) CLOCAL : local connection, no modem contol CREAD : enable receiving characters */ newtio.c_cflag = BAUDRATE | CS8 | CLOCAL |CREAD; /* IGNPAR : ignore bytes with parity errors ICRNL : map CR to NL (otherwise a CR input on the other computer will not terminate input) IGNBRK : Ignore break condition. otherwise make device raw (no other input processing) */ newtio.c_iflag = IGNPAR | ICRNL | IGNBRK; /* Raw output. */ newtio.c_oflag = 0; newtio.c_cc[VTIME] =2; //read 2 sec blokkeren, zo geeft u de powermeter genoeg tijd //om zijn data te versturen
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
92
Vereiste instellingen voor de Extech 380801 Default RS-232 Communications Settings Baud Rate: 9600; Stop bit: 1; Data bits: 8; Parity: None NOTE: Software developers must ensure that DTR provides 10V (or higher) and RTS provides -10V (or lower). Voltage (10V, -10V) from DTR and RTS is used to generate the RS-232 signal. DTR is usually enabled (10V) but RTS must be disabled in order to provide -10V. To accomplish this in BASIC, add RS in the OPEN command: OPEN "COM1: 9600, N, 8, 1, CS, DS, CD, RS" as #1
De rts lijn disablen is een must
Hierop heb ik lang gezocht ... en het zijn maar twee regeltjes.
sercmd = TIOCM_RTS; ioctl(fd, TIOCMBIC, &sercmd)
We gebruiken hier voor de ioctl klasse, ioctl.h includen dus. Open fd = open(MODEMDEVICE, O_RDWR );
De functie open wordt gebruikt om seriele poort te openen, u krijgt een int waarde terug die u dan kan gebruiken in de read en write functies. Deze functie bevindt zicht in de fcntl klasse dus fcntl.h includen. Read & Write Deze twee functies bevinden zich in de unistd klasse, unistd.h includen dus. Write tosend[0] = chartosend ; if (write(fd,tosend ,1) < 1)
U geeft drie argumenten mee aan de write functie: - fd Dit gebruiken om de seriële poort aan te spreken. - char[] Een array van chars dat u zou willen versturen. - int Hoeveel chars van de array u zou willen versturen (in ons geval altijd één byte/char). De write functie returned ook een nul of een één, respectievelijk niet of wel verstuurd. Read
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
93
res = read(fd,buf,aantBytes)
U geeft drie argumenten mee aan de read functie: - fd Dit gebruiken om de seriële poort aan te spreken - char [] (buf) Array van chars die u wilt laten opvullen door de read functie - aantbytes Hoeveel bytes u maximum zou willen lezen van de buffer van uw seriële poort. Dus bijvoorbeeld de Power meter stuur 20 bytes en u geeft aan dat u er maar vijf wilt lezen dan lees u er ook maar vijf in en schrijft u die dan naar de array van chars (buf []), de andere 15 bytes blijven dan in de buffer zitten. Maar pas hier meer op dat u de buffer niet laat overlopen want die bytes bent u dan ook kwijt! Let wel op als de Power meter vijf bytes stuurt en jij geeft aan dat u er 20 wilt lezen dan zal u maar vijf bytes in lezen en er ook maar vijf wegschrijven naar de array van chars (buf []). Protocoll Extech 380801 Soorten bytes
- Start byte Dit is altijd twee - Stop byte Dit is altijd drie - Data bytes - Aantal van data bytes is afhankelijk van wat er gevraagd wordt Gewoon een waarde is drie bytes (Volt, Ampère, Watt ...). Status van de Extech 380801 één byte. Data blocks
U hebt twee soorten data blocks. Een block voor een waarde (Volt, Ampère, Watt ...) ziet er dan zo uit.
2;128;62;44;3
Block voor een status (ready,busy):
2;129;3
Ontcijferen van een block
Voorbeeld: 2;4;17;35;3
2 en 3 geven aan dat de data volledig is doorgestuurd. Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
94
Range De tweede byte, hier vier dus geeft aan over welke range het gaat.
lijst van ranges * Decimaal Range * 3 200.0 v * 4 1000 V * 5 Hz * 49 2.000 A * 33 20.00 A * 192 200.0 W * 193 20000 W * 208 PF * 255 HOLD
Dus wij zitten bij dit voorbeeld in de range van (vier) 1000V. Waarde Om de waarde te kunnen ontcijferen hebben we de derde en de vierde byte nodig.
derde byte = 17 vierde byte = 35
We plaatsen ze dan in de volgende volgorde.
35 <-> 17 0 0 1 0 0 0 1 15 14 13 12 11 10 9
1 8
<->
0 7
0 6
0 5
1 4
0 3
0 2
0 1
1 0 //volgorde van de bits
- Bit 0 staat voor de polariteit, een bit waarde van 1 staat voor + en een bit waarde voor 0 staat -, maar bij het meten van Hz staat 0 voor KHz en 1 MHz - Bit 1: meest beduidende digit (0-1) - Bit 2-5: 2de digit (0-9)(0000-1001) - Bit 6-9: 3de digit (0-9)(0000-1001) - Bit 10-13: minst beduidende digit (0-9)(0000-1001) - Bit 14-15: plaats van de komma
Plaats van de komma: 00 = geen komma (0000) 01 = helemaal rechts (000.0) 10 = int midden (00.00) 11 = helemaal links (0.000) Noot!! Alle nibles moeten omgekeerd geïnterpreteerd worden. Dit wil zeggen als bijvoorbeeld bit 2-5 = 1000. Dan betekent het niet dat het een waarde 8 heeft maar een waarde 1!
In het geval van het voorbeeld (17,35): - Bit 0 = 1, dus + Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
95
-
Bit Bit Bit Bit Bit
1 = 0, dus meest beduidende digit = 0 2-5 = 0100, dus 2de digit = 2 6-9 = 1100, dus 3de digit = 3 10-13 = 1000, dus minst beduidende digit = 1 14-15 = 00, dus geen komma
We bekomen dan als we de digits achter elkaar plaatsen 0232. We hebben geen komma dus blijft het 0232. We dat ook dat de range 1000V is en dus bekomen we een volledige waarde van 232V. Range & waarde in code Waarde: double dechiperData(int ibyte1, int ibyte2){ int idigit1 =0; //eerste digit if (ibyte1 & 2){ idigit1 = idigit1+1; } int idigit2 =0; //tweede digit if (ibyte1 & 4){ idigit2 = idigit2 +8; } if (ibyte1 & 8){ idigit2 = idigit2 +4; } if (ibyte1 & 16){ idigit2 = idigit2 +2; } if (ibyte1 & 32){ idigit2 = idigit2 +1; } int idigit3 =0; //derde digit if (ibyte1 & 64){ idigit3 = idigit3 +8; } if (ibyte1 & 128){ idigit3 = idigit3 +4; } if (ibyte2 & 1){ idigit3 = idigit3 +2; } if (ibyte2 & 2){ idigit3 = idigit3 +1; } int idigit4 = 0; //4de digit if (ibyte2 & 4){ idigit4 = idigit4 +8; } if (ibyte2 & 8){ idigit4 = idigit4 +4; } if (ibyte2 & 16){ idigit4 = idigit4 +2; } if (ibyte2 & 32){ idigit4 = idigit4 +1; } //komma int idecimalpoint = 0; if (ibyte2 & 64){ idecimalpoint = idecimalpoint+1; } if (ibyte2 & 128){ idecimalpoint = idecimalpoint +2;
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
96
} double ivalue ivalue return
ivalue = 0; = idigit1 * 1000 +idigit2*100 + idigit3*10 + idigit4 *1; = ivalue / pow(10,idecimalpoint); ivalue;
}
Dus met bit operaties ga ik controleren of er op de posities 0 1 2 4 8 16 32 64 128 een 1 of een 0 staat, zo kan ik dan de waarde van elke digit verhogen zou er een 1 voorkomen. Dan als we veronderstellen dat er geen komma is en er 4 digits zijn, kunnen we zeggen dat de eerste digit een duizendtal, de tweede digit een 100 tal, de derde digit een tiental en de vierde digit gewoon een getal is. Deze dan met elkaar optellen. Om dan nog de komma op de juiste plaats te krijgen deel ik som van mijn 4 digits door 10 tot macht van mijn komma bits. Bijvoorbeeld de som van mijn digits bedraagt 0232 en de waarde van mijn komma bits is 0 (00).
0232 / 10^0 = 0232 / 1 = 0232
Range: char *dechiperRange(int ibyte){ char *rrange; //ranges hebben een vaste waarde dus een switch gebruiken //zie protocol manual extecht 380801 voor meer info switch ( ibyte ) { case 3 : rrange = "200.0V"; break; case 4 : rrange = "1000.0V"; break; case 5 : rrange = "Hz"; break; case 49 : rrange = "2.000A"; break; case 33 : rrange = "20.00A"; break; case 192 : rrange = "200.0 W"; break; case 193 : rrange = "2000 W"; break; case 208 : rrange = "PF"; break; case 255 : rrange = "HOLD"; break; } cout<<"-------------bereken range--------------\n"; cout<<"range byte= " << ibyte << "\trange = "<< rrange <<"\n"; cout<<"-------------bereken range--------------\n"; return rrange;
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
97
}
Omdat we weten dat de ranges vooraf bepaald zijn kunnen we gewoon met een simpele switch dit achterhalen.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
98
Performance Info ophalen CPU Gebruik van de CPU(s) in %. Windows Gebruikte WMI klassen: Win32_Processor
Deze WMI klasse dient voor het aantal CPUs op te vragen. Win32_PerfRawData_PerfOS_Processor Met deze klasse kunnen we het CPU gebruik opvragen. Hoe ophalen
Aantal CPUs : wstring values[] = { L"CpuStatus" }; _wmi->get_wmi_values("SELECT * FROM Win32_Processor", values, 1); for( uint i = 0; i < _wmi->_wmiData.size(); i++ ) { if( _wmi->_wmiData[0][0].boolVal = true) _onlineCpuCount++; }
Door alles op te vragen van ‘Win32_Processor’ kunnen we in een for lusjes alle elementen dat de WMI klasse returned gaan iterenen en zo kunnen we het aantal CPUs bekomen Performance data ophalen: vector arrPercentProcessorTime; (uint i=0; i<_cpuCount; i++) { _100nsec_timer_inv* percentProcessorTime = new perf_100nsec_timer_inv(); percentProcessorTime->get_vars(L"PercentProcessorTime","SELECT * FROM Win32_PerfRawData_PerfOS_Processor",i,1,_wmi); arrPercentProcessorTime.push_back(percentProcessorTime);
Voor elke CPU perfomance data ophalen, de data die u hier mee ophaalt is niet duidelijk, het is zoals de naam van de WMI klasse aantoont, raw data, u moet de data twee maal ophalen en dan kan u er een formule op toepassen die dan mooi het CPU gebruik berekend Linux Gebruikte bestanden
/proc/stat: > cat /proc/stat cpu 2255 34 2290 22625563 6290 127 456 cpu0 1132 34 1441 11311718 3675 127 438 cpu1 1123 0 849 11313845 2614 0 18 intr 114930548 113199788 3 0 5 263 0 4 [... lots more numbers ...] ctxt 1990473 btime 1062191376 processes 2915 procs_running 1 procs_blocked 0
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
99
/proc/cpuinfo: > cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 5 model name : Pentium II (Deschutes) stepping : 2 cpu MHz : 400.913520 cache size : 512 KB fdiv_bug : no hlt_bug : no sep_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 2 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 mmx fxsr bogomips : 399.77
Verklaring
/proc/stat: Hierin vind u informatie over de kernel activiteit, de getallen dit u hierin kunt aflezen blijven stijgen vanaf de computer is opgestart. de eerste lijn geeft het totale CPU gebuik aan. De daarop volgende lijnen geven CPU gebruik aan van elke CPU afzonderlijk. De getallen na ‘CPU’ betekenen het volgende (van link naar rechts) - user: normal processes executing in user mode - nice: niced processes executing in user mode - system: processes executing in kernel mode - idle: twiddling thumbs - iowait: waiting for I/O to complete - irq: servicing interrupts - softirq: servicing softirqs De intr lijn geeft info over de interrupt sinds boots, het eerste getal is een opsomming van alle interrupts en de daarop volgende getallen zijn het aantal interrupts voor een bepaalde interrupt. The ctx lijn geeft het aantal context switches tussen alle cpus The btime toont de tijd van wanneer het systeem is geboot geweest in seconden. The processes lijn toont het aantal processen en threads dat er gecreerd zijn. The procs_running toont het aantal processen dat momenteel aan het draaien zijn op de CPU(s). The procs_blocked lijn toont het aantal processen dat momenteel geblokeerd zijn, wachtend op I/O tot dat ze afgehandeld zijn. /proc/cpuinfo: Informatie over de processor zoals model,type and performance. Bestand bestaat uit twee kolommen. De eerste kolom toont het type van info en de tweede kolom de info.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
100
Hoe Parsen
/proc/stat: void CpuInfo::ReadCpuRawData()//cpu_options *opts) { string line; string line2; string device; bool bkeepReading = true; ifstream file("/proc/stat"); // try and open the file if(file.is_open()) // if it's open { do{ // until we read a line that doesnt start with cpu. getline(file, line); // get the rest on the line into the string line2 = line.substr(line.find(" ")+1); device = line.substr(0, line.find(" ")); // cout << "device \t\t = " << device << "\n"; if (device.substr(0, 3).compare("cpu") == 0){ istringstream lineStream(line2); // dump it into a stringstream so we can use istream_iterators on it vector lineNums; copy(istream_iterator(lineStream), istream_iterator(), back_inserter(lineNums)); // copy the ints into the vector CpuData ocpuData; ocpuData.cpu = lineNums[0]; ocpuData.nice = lineNums[1]; ocpuData.system = lineNums[2]; ocpuData.idle = lineNums[3]; cpuListUsage.push_back(ocpuData); } else{ bkeepReading = false; } } while(bkeepReading); } file.close(); /* cout<< "--------cpuListUsage---------- \n"; printData(cpuListUsage); cout<< "--------cpuListUsageOlder---------- \n"; printData(cpuListUsageOlder); */ }
In APUS SMT wordt CPU gebruik data op deze manier geparst: blijven parsen zolang het begin van een lijn met CPU start, zo ja de vier opvolgende getallen in een array bijhouden zodat er later een berekening kan gebeuren. /proc/cpuinfo: list CpuInfo::GetCpuInfo(){ m_oCpuMapList.clear(); char buffer[255]; char name[255]; char value[255]; FILE *ncpufp = fopen("/proc/cpuinfo", "r"); fgets(buffer, sizeof(buffer), ncpufp); while (!feof(ncpufp)) { sscanf(buffer, "%[^:]%*[ :]%[^\n]", name , value); //printf("value = %s \nname =%s \n\n", value, name ); if (buffer[0] == '\n'){ //when you have two or more cpus the cpu date will be seperated by a '\n' in /proc/cpuinfo file
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
101
//so if we encounter a 'n' we know we finished with reading all data for a cpu and we put all that data in a vector m_oCpuMapList.push_back( m_oCpuMap ); m_oCpuMap.clear( ); } else{ string key = ReplaceInString(name, " ", "_"); m_oCpuMap [key] = value; } fgets(buffer, sizeof(buffer), ncpufp); } fclose(ncpufp); return m_oCpuMapList; }
Berekening double CpuInfo::GetCpuUsage(int cpuNumber , bool nice){ int i = cpuNumber; double usage; usage = 0; double used; double total; used = (cpuListUsage[i].cpu - cpuListUsageOlder[i].cpu) + (cpuListUsage[i].system - cpuListUsageOlder[i].system); if (nice){ used = used + (cpuListUsage[i].nice - cpuListUsageOlder[i].nice); } total = (cpuListUsage[i].cpu - cpuListUsageOlder[i].cpu) + (cpuListUsage[i].system - cpuListUsageOlder[i].system) + (cpuListUsage[i].idle - cpuListUsageOlder[i].idle) + (cpuListUsage[i].nice cpuListUsageOlder[i].nice); usage = used / total; return usage * 100; // % }
Voorbeeld lijn één: cpu 2255 34 2290 22625563 6290 127 456 Voorbeeld lijn twee: cpu 2260 35 2291 22625564 6291 127 456 Lijn één en twee stellen beide een lijn voor in ‘/proc/stat’ maar op een verschillend tijdstip. Door deze lijn twee maal geparst te hebben kunt u CPU gebruik in procent weergeven. We hebben enkel de eerste vier waardes nodig van een lijn. De eerste waarde is het CPU gebruik, de tweede is de ‘nice’ waarde en de derde en de vierde staan voor ‘system’ en ‘idle’. Met deze formule kan CPU gebruik berekend worden:
double CpuInfo::GetCpuUsage(int cpuNumber , bool nice){ (Lijn2.cpu-Lijn1.cpu) + (Lijn2.system – Lijn1.system) /( (Lijn2.cpuLijn1.cpu) + (Lijn2.system – Lijn1.system) + (Lijn2.nice-Lijn1.nice) + (Lijn2.idle – Lijn1.idle) )
Geheugen Geheugen gebruik in bytes/sec, vier waardes zijn hiervoor nodig:
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
102
Totaal van het werkgeheugen, gebruik van het werkgeheugen, totaal van de swap, gebruik van de swap Windows Gebruikte klassen
Winbase.h Om het geheugen verbruik op te vragen kan u hier voor best de ‘winbase.h’ klasse voor gebruiken. Want in ‘winbase.h’ zit een structure (MEMORYSTATUSEX) die deze waarden opslaat. Hoe ophalen void Memory::refresh () { MEMORYSTATUSEX meminfo; meminfo.dwLength = sizeof (meminfo); GlobalMemoryStatusEx(&meminfo); _totPhys = meminfo.ullTotalPhys; _availPhys = meminfo.ullAvailPhys; _totSwap = meminfo.ullTotalPageFile; _availSwap = meminfo.ullAvailPageFile; }
Linux Gebruikte bestanden
#include <sys/sysinfo.h>: struct sysinfo sys; if (sysinfo(&sys) >= 0) { _totPhys = sys.totalram; _availPhys = sys.freeram; _totSwap = sys.totalswap; _availSwap = sys.freeswap; } else { _totPhys = 0; _availPhys = 0; _totSwap = 0; _availSwap = 0; }
/proc/meminfo: > cat /proc/meminfo MemTotal: 1018132 kB MemFree: 597464 kB Buffers: 20220 kB Cached: 197856 kB SwapCached: 0 kB Active: 243500 kB Inactive: 121264 kB HighTotal: 0 kB HighFree: 0 kB LowTotal: 1018132 kB LowFree: 597464 kB SwapTotal: 2048248 kB SwapFree: 2048248 kB Dirty: 884 kB Writeback: 0 kB . . .
Verklaring Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
103
#include <sys/sysinfo.h>: Sysinfo.h is een klasse die geheugen usage ophaalt en returned. #ifndef _SYS_SYSINFO_H #define _SYS_SYSINFO_H #include <sys/cdefs.h> __BEGIN_DECLS #define SI_LOAD_SHIFT 16 struct sysinfo { long uptime; /* Seconds since boot */ unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ unsigned long totalram; /* Total usable main memory size */ unsigned long freeram; /* Available memory size */ unsigned long sharedram; /* Amount of shared memory */ unsigned long bufferram; /* Memory used by buffers */ unsigned long totalswap; /* Total swap space size */ unsigned long freeswap; /* swap space still available */ unsigned short procs; /* Number of current processes */ unsigned short pad; /* explicit padding */ unsigned long totalhigh; /* Total high memory size */ unsigned long freehigh; /* Available high memory size */ unsigned int mem_unit; /* Memory unit size in bytes */ char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ }; int sysinfo(struct sysinfo *info) __THROW; __END_DECLS #endif
/proc/meminfo: Informatie over geheugengebruik, zowel fysiek als swap. Hoe Parsen
/proc/meminfo: void MemInfo::ReadMem(){ ifstream meminfo( "/proc/meminfo" ); char NameBuffer [ 256 ]; char ValueBuffer [ 256 ]; char DiscardBuffer [ 256 ]; // throw out the first three lines. The info is // redundant, and not available in 2.5 meminfo.getline( DiscardBuffer, 256 ); meminfo.getline( DiscardBuffer, 256 ); meminfo.getline( DiscardBuffer, 256 ); // now we get to the good stuff while ( ! meminfo.eof( ) ) { meminfo.get( NameBuffer, 256, ':' ); meminfo.get( DiscardBuffer, 2 ); // lose the : meminfo.get( ValueBuffer, 256, '\n' ); meminfo.get( DiscardBuffer, 2, ' ' ); // lose the \n -- specify ' ' or it will stop before the \n and not read it if ( NameBuffer [ 0 ] == 0 ) { break; } else { oMemoryMap [ NameBuffer ] = atoi( ValueBuffer) ; } } }
In APUS SMT wordt voor meminfo tijdens het parsen de eerste drie regels ingelezen in een ‘discardbuffer’, dan wordt voor de ‘:’ het type van info in de ‘namebuffer’ gestopt en na de ‘:’ de waarde van het type info in de ‘valuebuffer’ gestopt.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
104
Disk In kB/sec dat er gelezen wordt van de schijf en dat er geschreven wordt naar de schijf. Windows Gebruikte wmi klassen
Win32_LogicalDisk Deze klasse wordt gebruik om een onderscheid te kunnen maken tussen de types van LogicalDisks, bijvoorbeeld er moet geen performance data opgevraagd worden voor CRRoms. Win32_PerfRawData_PerfDisk_LogicalDisk Haalt rawData waarop we een formule kunnen gebruiken die ons dan reads of writes /sec berekend. Hoe ophalen
Onderscheid van de disks : //get disks _wmi->get_wmi_values("SELECT * FROM Win32_LogicalDisk", values2, 1); _diskCount = 0; for(uint i = 0;i<_wmi->_wmiData.size();i++) { Disk* disk = new Disk(_wmi, i); bool pushBackOrNot = false; if (disk->getDriveType()==0){ pushBackOrNot=false; } if (disk->getDriveType()==1){ pushBackOrNot=false; } if (disk->getDriveType()==2){ pushBackOrNot=false; } if (disk->getDriveType()==3){ pushBackOrNot=true; } if (disk->getDriveType()==4){ pushBackOrNot=true; } if (disk->getDriveType()==5){ pushBackOrNot=false; } if (disk->getDriveType()==6){ pushBackOrNot=false; } if (pushBackOrNot){ _disks.push_back(disk); _diskCount = _diskCount + 1; }
We vragen alle disks op uit ‘Win32_LogicalDisk’ en voor elke disk kunnen we de drivetype opvragen en zo bijvoorbeeld CDRoms en USB sticks filteren. Performance data ophalen: for (int i=0;i<_diskCount;i++) { perf_counter_bulk_count* bytesWritePersec = arrDiskWriteBytesPerSec[i]; Disk* disk = _disks[i]; ostringstream s; s << "SELECT * FROM Win32_PerfRawData_PerfDisk_LogicalDisk WHERE Name ='" << disk->getName() << "'";
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
105
string wql = s.str(); bytesWritePersec->get_vars(L"DiskWriteBytesPerSec",wql.c_str(),0,2,_wmi); disk->setDiskWriteBytesPerSec (bytesWritePersec->get_count()); } for (int i=0;i<_diskCount;i++) { perf_counter_bulk_count* bytesReadPersec = arrDiskReadBytesPerSec[i]; Disk* disk = _disks[i]; ostringstream s; s << "SELECT * FROM Win32_PerfRawData_PerfDisk_LogicalDisk WHERE Name ='" << disk->getName() << "'"; string wql = s.str(); bytesReadPersec->get_vars(L"DiskReadBytesPerSec",wql.c_str(),0,2,_wmi); disk->setDiskReadBytesPerSec (bytesReadPersec->get_count()); }
Voor elke disk halen we de ruwe data op voor het aantal bytes dat er gelezen worden en geschreven worden per seconde. Linux Gebruikte bestanden
/proc/diskstat: >
cat /proc/diskstat 2 0 fd0 0 0 0 0 0 0 0 0 0 0 0 8 0 sda 852224 105596 33179026 5871592 17514424 22223526 317899060 2693971460 0 131824752 2699842752 8 1 sda1 375 1370 1499 6884 8 2 sda2 28 440 157 1672 8 3 sda3 0 0 0 0 8 4 sda4 957295 33177072 39736316 317890528 8 16 sdb 852756 108014 33792640 5979476 17415211 22322739 317899060 2505152820 0 130904728 2511132008 8 17 sdb1 429 1686 1499 6884 8 18 sdb2 26 408 157 1672 8 19 sdb3 0 0 0 0 8 20 sdb4 960252 33790466 39736316 317890528 8 32 sdc 2725788 2156264 78130472 738946916 5628224 1331771 107237072 1350624800 0 41509852 2089789240 8 33 sdc1 4883154 78130456 6964507 107237080 8 48 sdd 2703380 2137425 77469352 733073192 5581293 1276600
/proc/stat: > cat /proc/stat cpu 2255 34 2290 22625563 6290 127 456 cpu0 1132 34 1441 11311718 3675 127 438 cpu1 1123 0 849 11313845 2614 0 18 intr 114930548 113199788 3 0 5 263 0 4 [... lots more numbers ...] ctxt 1990473 btime 1062191376 processes 2915 procs_running 1 procs_blocked 0
Verklaring
/proc/diskstat: U kunt Disk info (read/sec, write/sec, ..) parsen, uitlezen van ‘/proc/diskstat’, u vindt er volgende info in terug. Met de getallen voor de naam van de disk of partitie kan u het type van disk afleiden, bijvoorbeeld IDE. Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
106
De getallen achter de naam hebben de volgende betekenis: Veld 1 -- # reads issued Veld 2 -- # reads merged Veld 3 -- # sectors read Veld 4 -- # milliseconds spent reading Veld 5 -- # writes completed field 6 -- # writes merged Veld 7 -- # sectors written Veld 8 -- # milliseconds spent writing Veld 9 -- # I/Os currently in progress Veld 10 -- # milliseconds spent doing I/Os Veld 11 -- weighted # milliseconds spent doing I/Os /proc/stat: Het aantal ticks dat u in ‘/proc/stat’ kunt parsen wordt gebruikt om heel nauwkeurig bijvoorbeeld reads / sec te berekenen. Ik heb dit ondervonden toen ik de source code van iostat aan het analyseren was. Hoe Parsen
/proc/diskstat: void PartitionInfo::ReadRawPartData(){ cpufp = fopen("/proc/stat", "r"); string disk; const char *scan_fmt = NULL; switch (kernel) { case 4: scan_fmt = "%4d %4d %*d %*s %u %u %llu %u %u %u %llu %u %*u %u %u"; break; case 6: scan_fmt = "%4d %4d %s %u %u %llu %u %u %u %llu %u %*u %u %u"; break; } handle_error("logic error in get_kernel_stats()", !scan_fmt); rewind(iofp); while (fgets(buffer, sizeof(buffer), iofp)) { int items; struct blkio_info blkio; items = sscanf(buffer, scan_fmt,&blkio.major, &blkio.minor, blkio.name, &blkio.rd_ios, &blkio.rd_merges,&blkio.rd_sectors, &blkio.rd_ticks, &blkio.wr_ios, &blkio.wr_merges,&blkio.wr_sectors, &blkio.wr_ticks, &blkio.ticks, &blkio.aveq); if (items == 7) { blkio.rd_sectors = blkio.rd_merges; blkio.wr_sectors = blkio.rd_ticks; blkio.rd_ios = 0; blkio.rd_merges = 0; blkio.rd_ticks = 0; blkio.wr_ios = 0; blkio.wr_merges = 0; blkio.wr_ticks = 0; blkio.ticks = 0; blkio.aveq = 0; items = 12; blkio.disk = disk; } else{ blkio.disk ="no partition"; disk = blkio.name; } if (IDE_DISK_MAJOR(blkio.major) || SCSI_DISK_MAJOR(blkio.major)){ new_blkio.push_back(blkio); } }
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
107
Er wordt eerst gecontroleerd op kernel versie en dan wordt er ingesteld van hoe diskstats moet ingelezen worden. Alle data wordt na het lezen bijgehouden in een object blkio en die dan weer wordt bijgehouden een vector, ook wordt er gecontroleerd als het om een IDE of een SCSI disk gaat anders wordt de data niet bijgehouden.
Netwerk Het netwerkverbuik (upload en download) van alle network interfaces in kB/sec. Windows Gebruikte WMI klassen
Win32_NetworlAdapter Deze WMI klasse dient om het aantal network interfaces op te vragen Win32_PerfRawData_Tcpip_NetworkInterface Met deze klasse kunnen we het netwerk verbruik opvragen. Hoe ophalen
Performance data ophalen: for (int i=0;i<_ntwInterfaceCount;i++) { perf_counter_counter* bytesSentPersec = arrBytesSentPerSec[i]; bytesSentPersec->get_vars(L"BytesSentPersec","SELECT * FROM Win32_PerfRawData_Tcpip_NetworkInterface",i,2,_wmi); NetworkInterface* ntwInterface = _ntwInterfaces[i]; ntwInterface->setSentBytes (bytesSentPersec->get_count()); } for (int i=0;i<_ntwInterfaceCount;i++) { perf_counter_counter* bytesReceivedPersec = arrBytesReceivedPerSec[i]; bytesReceivedPersec->get_vars(L"BytesReceivedPersec","SELECT * FROM Win32_PerfRawData_Tcpip_NetworkInterface",i,2,_wmi); NetworkInterface* ntwInterface = _ntwInterfaces[i]; ntwInterface->setReceivedBytes (bytesReceivedPersec->get_count()); } for (int i=0;i<_ntwInterfaceCount;i++) { perf_counter_rawcount* bandwidth = new perf_counter_rawcount(); bandwidth->get_vars(L"CurrentBandwidth","SELECT * FROM Win32_PerfRawData_Tcpip_NetworkInterface",i,_wmi); NetworkInterface* ntwInterface = _ntwInterfaces[i]; ntwInterface->setBandwidth (bandwidth->get_count()); }
Voor elke interface halen we het aantal bytes/sec dat verstuurd en ontvangen werd en ook de ingestelde bandwidth wordt opgevragen. Voor het aantal ontvangen en verstuurde bytes moeten we dan weer twee maal dezelfde data opvragen op een verschillende tijdstip om er dan een formule op te gebruiken. Linux U kan de waardes bereken door om een bepaald interval ‘/proc/net/dev’ te parsen en de geparste waardes dan met elkaar te verglijken. Gebruikte bestanden
/proc/net/dev:
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
108
Inter-|
Receive
|
Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed lo: 4007 64 0 0 0 0 0 0 0 0 0 eth0: 0 0 0 0 0 0 0 0 0 0 0 0 eth1:128457813 175721 1 24 0 14462648 111284 0 0 0 0 sit0: 0 0 0 0 0 0 0 0 0 0 0 0
0
0
0
4007
64
0
0
0
0 0
0
0
0
0 0
0
0
0
Verklaring
/proc/net/dev: Het dev bestand bevat de status van elk netwerkapparaat. Bijvoorbeeld het aantal gezonden en ontvangen bytes, aantal errors , collisions enz. zoals ‘/proc/stat’ blijven de getallen hierin stijgen vanaf het besturingssysteem is opgestart. Het is dus mogelijk om heel de tabel twee keer achter elkaar te parsen, de getallen dan van elkaar af te trekken en zo bekom u dan bytes/sec voor eender welk type in de tabel. Hoe Parsen
/proc/net/dev: for (int i=0;i<_ntwInterfaceCount;i++) { perf_counter_counter* bytesSentPersec = arrBytesSentPerSec[i]; bytesSentPersec->get_vars(L"BytesSentPersec","SELECT * FROM Win32_PerfRawData_Tcpip_NetworkInterface",i,2,_wmi); NetworkInterface* ntwInterface = _ntwInterfaces[i]; ntwInterface->setSentBytes (bytesSentPersec->get_count()); } for (int i=0;i<_ntwInterfaceCount;i++) { perf_counter_counter* bytesReceivedPersec = arrBytesReceivedPerSec[i]; bytesReceivedPersec->get_vars(L"BytesReceivedPersec","SELECT * FROM Win32_PerfRawData_Tcpip_NetworkInterface",i,2,_wmi); NetworkInterface* ntwInterface = _ntwInterfaces[i]; ntwInterface->setReceivedBytes (bytesReceivedPersec->get_count()); } for (int i=0;i<_ntwInterfaceCount;i++) { perf_counter_rawcount* bandwidth = new perf_counter_rawcount(); bandwidth->get_vars(L"CurrentBandwidth","SELECT * FROM Win32_PerfRawData_Tcpip_NetworkInterface",i,_wmi); NetworkInterface* ntwInterface = _ntwInterfaces[i]; ntwInterface->setBandwidth (bandwidth->get_count()); }
De eerste twee lijnen inlezen maar niets mee doen, dan voor elke interface/lijn die u tegenkomt voor de ‘:’ de naam bijhouden en alle waardes achter de : in een vector stoppen die dan op zich weer wordt bijgehouden een netwerkinterface object. Berekening double NetworkPerfInfo::GetPerSec(int interface, int datarequested){ if (interface < oNetDevList.size() && interface >= 0 && interface <= 15){ // if requested inteferface return ( oNetDevList[interface].getData(datarequested) oNetDevOlderList[interface].getData(datarequested) ) / timeDiff; }
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT
109
else{ return -1337; // -1 or -1337, you can change this if you want just keep it negatif so you can catch it in the main file ! } }
Elke waarde in de ‘/proc/net/dev’ tabel wordt bijgehouden in een array en deze dan weer in een object. Zo kan de berekening gebeuren zou ‘/proc/net/dev’ twee maal geparst worden met de volgende formule:
oNetDevList[interface].getData(datarequested) NetDevOlderList[interface].getData(datarequested)
) / timeDiff;
‘timeDiff’ is het aantal seconden tussen de eerste en de tweede parsing,dan wordt de gekozen data van elkaar afgetrokken en zo bekom u bijvoorbeeld het aantal verzonden bytes/sec.
Conclusie Dankzij de ‘PerformanceInfoContainer’ klasse die als tussenlaag functioneert tussen de ‘TaskHandler’ en de geparste data is APUS SMT een makkelijk uit te breiden applicatie. APUS SMT kan worden gebruikt als server applicatie voor APUS of standalone gebruikt worden om te loggen.
Dieter Vandroemme Leandro Cavaliere
Sizing Servers: APUS en APUS SMT
APUS en APUS SMT