pronto.ee

Tomorrow will be cancelled due to lack of interest

PHP: sizeof vs count vs empty

PHP

PHP on praeguseks juba võrdlemisi eakas programmeerimiskeel / infrastruktuur, selle esimene ametlik versioon ilmus 8. juuni, 1995. Pea kolme aastakümne jooksul on see toonud leiva lauale mitmele põlvkonnale tarkvaraarendajatest, PHP põhine WordPress on de facto kodulehtede ehitamise kullastandard ning tegemist on ideaalse platvormiga algajale. Kuid sellel on ka mitu suurt viga ja üks neist on see, et asju on võimalik teha mitut moodi. Ning tavaliselt on üks neist selgelt parem.

Järgnev artikkel võrdleb üsna tüüpilist stsenaariumit kus programmil on vaja teada enne andmete töötlemist kas massiivis üldse on andmeid. Selleks on mitu võimalust. Esimese hooga suutsin ma leida viis erinevat viisi seda teha ja kirjutasin nende võrdlemiseks kiire testskripti:

<?php

$data1 = ['one', 'two', 'three'];
$data2 = array_fill(0, 1000000, 'something');
$functions = ['e', 'c', 's', 'x', 'y'];
$times = 10000000;

echo phpversion() . "\n";

foreach ($functions as $f) {
    echo "Function: $f small\n";
    $start = microtime(true);
    for ($i = 0; $i < $times; $i++) {
        $f($data1);
    }
    echo 'Time elapsed: ' . (microtime(true) - $start) . "\n";
    echo "Function: $f big\n";
    $start = microtime(true);
    for ($i = 0; $i < $times; $i++) {
        $f($data2);
    }
    echo 'Time elapsed: ' . (microtime(true) - $start) . "\n";
}

function e(array $data)
{
    return empty($data);
}

function c(array $data)
{
    return count($data) > 0;
}

function s(array $data)
{
    return sizeof($data) > 0;
}

function x(array $data)
{
    return (bool)$data;
}

function y(array $data)
{
    return $data !== [];
}

Ettetõttavalt tuleb erinevad variandid on isoleeritud eraldiseisvatesse funktsioonidesse mis ei ole just kõige tõhusam viis seda teha, kuid kuna sellega kaasnev ballast on kõikide võimaluste jaoks sama, siis ei ole see probleem. Allpool on tulemused:

5.6.40-pl17-zoneos
Function: e small
Time elapsed: 0.68565702438354
Function: e big
Time elapsed: 0.67864203453064
Function: c small
Time elapsed: 1.0022921562195
Function: c big
Time elapsed: 0.99124312400818
Function: s small
Time elapsed: 1.0054261684418
Function: s big
Time elapsed: 1.0156378746033
Function: x small
Time elapsed: 1.2238240242004
Function: x big
Time elapsed: 12.408221960068
Function: y small
Time elapsed: 0.86892318725586
Function: y big
Time elapsed: 0.8515739440918
7.4.33
Function: e small
Time elapsed: 0.18914604187012
Function: e big
Time elapsed: 0.18664002418518
Function: c small
Time elapsed: 0.20966601371765
Function: c big
Time elapsed: 0.20747518539429
Function: s small
Time elapsed: 0.20873785018921
Function: s big
Time elapsed: 0.20844912528992
Function: x small
Time elapsed: 0.19939112663269
Function: x big
Time elapsed: 0.20096492767334
Function: y small
Time elapsed: 0.21982216835022
Function: y big
Time elapsed: 0.21845602989197
8.4.1
Function: e small
Time elapsed: 0.17859983444214
Function: e big
Time elapsed: 0.1792311668396
Function: c small
Time elapsed: 0.19513893127441
Function: c big
Time elapsed: 0.19733500480652
Function: s small
Time elapsed: 0.19513511657715
Function: s big
Time elapsed: 0.1961989402771
Function: x small
Time elapsed: 0.17471885681152
Function: x big
Time elapsed: 0.17510986328125
Function: y small
Time elapsed: 0.21288394927979
Function: y big
Time elapsed: 0.21385288238525

Nagu näha viisin ma testid läbi kolme erineva PHP versiooniga (5.6, 7.4 ja 8.4). Tulemused on järgnevad:

Kõige kiirem viis on tüübi vahetamine (castimine) (bool)$data meetodil (praktikas kasutatakse seda nõnda: if ($arrayData) {...}). Aga. Kui andmete hulk on vähegi tõsine, siis PHP 5.6 ei suuda seda hallata ning sestap muutub antud meetod selle versiooni puhul (ilmselt kehtib see ka eelnevate versioonide kohta) hoopis drastiliselt aeglasemaks. Et skript üldse mõistliku aja sees oma toimetamise lõpetaks kärpisin ma selle versiooni puhul suure massiivi elementide arvuks 100. Kõikidel muudel versioonidel on suures massiivis 1000000 elementi.

Paneme asjad järjekorda, kiiremast aeglasemaks:

  1. Tüübi vahetamine
  2. empty()
  3. count()
  4. sizeof()
  5. Tühja massiiviga võrdlemine

Nagu ma ennist mainisin pole PHP 5.6-s tüübi vahetamine mõistlik. Õnneks on see versioon juba nõnda vana, et kui keegi seda reaalselt praktikas kasutab, siis on kiirus kogu asja juures kõige väiksem mure.

empty() funktsioon on kohe järgmine. Seda on mõttekas kasutada näiteks siis kui mängu tulevad callback / callable funktsioonid.

count() sisaldab endas lisafunktsionaalsust, kuna ta võimaldab teada saada ka mitu elementi on massiivis. See teeb selle pisut aeglasemaks.

sizeof() on count() funktsiooni alias. See on veidike aeglasem kui count() kuna sisaldab endas sisemist suunamist.

Massiivide võrdlemine ei ole üleüldse hea mõte. Pealegi nagu näha on see kõige aeglasem viis teada saamaks, et andmeid pole.

Aga miks kõik see? Me räägime ju sekundi murdosadest? Ühest küljest ei olegi. Teisest küljest natuke siit ja natuke sealt ning sellest tingituna on mõned veebirakendused kiiremad kui teised, ei vaja nõnda jämedat rauda ehk siis hoiavad nõnda kokku inimeste aega ja raha.

Ning siin on üks tahk veel — see aitab hinnata programmeerija kompetentsust. Kui ta on teadlik nendest nüanssidest, siis tähendab see seda, et ta on viitsinud süveneda, aru saada ning optimeerib oma käekirja ka väikestes detailides, rääkimata suurtest.

Post a comment