Qlist-spor h1>

Denne artikkelen viser en sammenligning mellom QSet og QList for metoden inneholder (). Den undersoker ytelsen av innholdet () for forskjellige storrelser av beholdere, nemlig forskjellige storrelsesordener av beholderstorrelsene (1, 10, 100, 1000 etc.). Resultatet undersokes ved hjelp av QBENCHMARK-makroen fra QTestLib.

Vi forventer at QList har en O (n) kompleksitet for inneslutningstesting og QSet potensial O (1) kompleksitet for inneslutningstesting.

Soker gjennom en usortert sekvensiell container som QList krever undersokelse av hvert enkelt element og resulterer i en runtime kompleksitet O (n). Pa den annen side er QSet en hash-bordsbasert container. I motsetning til sekventielle beholdere holder settene ikke elementer i den rekkefolgen de ble satt inn. Dette har noen fordeler. For eksempel er inneslutningstesting raskere for sett med potensiell O (1) kompleksitet, da vi ikke trenger a utfore et line rt sok.

Sett har denne egenskapen takket v re en teknikk som kalles hashing. En hash-funksjon beregner et heltall (hash-kode) fra en gjenstand. En hash-funksjon produserer ikke nodvendigvis en unik hashkode for hvert objekt. Normalt kartlegger den en nokkel til en botte som kan inneholde ett eller flere elementer (antallet av disse bossene kan eksponeres med QSet :: kapasitet ()). Beholderen deretter iterates over innholdet i botte til den finner en kamp. I beste fall, med enten ingen kollisjoner og alle skuffer enten tomme eller med et enkelt element, vil kontrollen for inneslutning ta konstant O (1) tid.

Merk: Valget av den sekventielle beholderen (QList, QVector eller QLinkedList) vil ha liten effekt sammenlignet med QSet for inneslutningstest for storrelsen pa beholdere undersokt i denne artikkelen. Likevel bor vi nevne at QList lagrer pekerne til elementene i stedet for elementene selv. Det er QVector som lagrer sine varer etter hvert i minnet. Du kan lese mer om dette i denne Qt Quarterly – Inside the Qt 4 Containers artikkelen. Du er ogsa velkommen til a se selv og endre typen av beholderen i testen.

Testing med QBENCHMARK.

Vi skal male ytelsen til koden var med QBENCHMARK, som er en utvidelse av QTestLib-rammeverket. For a male utforelsen av en kode er alt vi trenger a gjore, a plassere den i krollede parentes som foregar av makroen QBENCHMARK. Ytelsen kan males basert pa veggtid (standard), CPU tick teller, valgrind / callgrind eller en event teller. I dette eksemplet bruker vi standardmetoden basert pa veggtid.

Vart mal er a identifisere storrelsen pa beholderen, for hvilken inneslutningstesting kan pavirke ytelsen til et program pa en slik mate at det er merkbart for brukeren. Til dette formal oppretter vi containere med storrelser som representerer forskjellige storrelsesordener som 1, 10, 100, 1000, 10000, 100000 og 1000000.

Merk: For a bruke QTestLib ma vi legge inn folgende linje i var prosjektfil:

Implementeringsdetaljer.

For a utfore testen oppretter vi en klasse som heter TestContainer. Selve testen vil bli utfort av den private sporet testContainment (). Vi utforer testen ved bruk av et datasett, noe som ikke er noe annet enn et bord av containertyper (QSet, QList) og de forskjellige storrelsene pa beholdere (1, 10, 100, 1000, 10000, 100000 og 1000000) som vi vil gjerne teste. Datasettet er opprettet ved metode testContainment_data (). Datametoden ma ha samme navn som testmetoden vedlagt ‘_data ()’. Vi introduserer ogsa en enum ContainerType for a skille mellom ulike containertyper.

La oss na se var data metode testContainment_data () som konstruerer testtabellen. Vi bruker metoden addColumn () for a legge til en kolonne for container type og container storrelse. Forlop skaper de enkelte testrader med QTest :: newRow (). Navnet pa testraden, dvs. argumentet i parentesene, er opprettet fra beholderens navn og storrelsen pa beholderen.

Datametoden skaper stort sett tabellen under:

Testmetoden selv, dvs. testContainment () kan ses nedenfor. QFETCH-makroen oppretter en lokal variabel ‘ContainerType-type’ og ‘int-storrelse’. Disse lokale variablene blir fylt med dataene fra testtabellen som ligger i testContainment_data (). Nar vi har dataene, kaller vi hjelperfunksjonen testContains ().

TestContains () rolle er a fylle containeren (QList eller QSet) med data. Siden vi vil at funksjonen skal fungere med en hvilken som helst container, har vi laget testContains () en malfunksjon. Malen funksjonen er bade erkl rt og definert i header filen.

Nar beholderen er fylt med data, utforer vi den faktiske testen med makroen QBENCHMARK som tester inneslutning av en enkelt verdi. Den heltallverdien vi sjekker er en vilkarlig negativ verdi. Siden vi bare befolket beholderen med ikke-negative verdier, kan vi v re sikre pa at den negative verdien ikke vil v re til stede i beholderen. Dette representerer worst case scenario for QList nar hele QListen ma sokes. Pastanden som kommer etter QBENCHMARK-lukkeboylene, er a sikre at «val» faktisk brukes og ikke optimaliseres bort av kompilatoren.

Vi kjorer testen fra main.cpp med QTest :: qExec ():

Testen gir folgende resultat:

********* Start testing av TestContainer *********

Config: Bruke QTest-biblioteket 4.8.0, Qt 4.8.0.

0.000038 msek per iterasjon (totalt: 81, iterasjoner: 2097152)

0.000040 msek per iterasjon (totalt: 84, iterasjoner: 2097152)

0.000038 msek per iterasjon (totalt: 81, iterasjoner: 2097152)

0.000086 msek per iterasjon (totalt: 91, iterasjoner: 1048576)

0.000049 msek per iterasjon (totalt: 52, iterasjoner: 1048576)

0,00055 msek per iterasjon (totalt: 73, iterasjoner: 131072)

0.000049 msek per iterasjon (totalt: 52, iterasjoner: 1048576)

0.0051 msek per iterasjon (totalt: 84, iterasjoner: 16384)

0.000049 msek per iterasjon (totalt: 52, iterasjoner: 1048576)

0,050 msek per iterasjon (totalt: 52, iterasjoner: 1024)

0.000049 msek per iterasjon (totalt: 52, iterasjoner: 1048576)

0,50 msek per iterasjon (totalt: 65, iterasjoner: 128)

0.000038 msek per iterasjon (totalt: 81, iterasjoner: 2097152)

5.1 msek per iterasjon (totalt: 83, iterasjoner: 16)

Totalt: 3 bestatt, 0 mislyktes, 0 hoppet over.

********* Ferdig testing av TestContainer *********

Hvis vi oppsummerer resultatene i et bord, kan vi se at QSet har O (1) kompleksitet for inneslutningstesting, med andre ord er resultatet av innholdet () -metoden uavhengig av antall oppforinger i QSet. Pa den annen side har QList O (n) kompleksitet for inneslutningstesting, og tiden oker line rt med antall elementer i listen.