PHP'de yazılan kodun hızını nasıl ölçebilirim? [kapalı]


118

Hangi sınıfın (hepsi aynı işi yapıyor) daha hızlı çalıştığını nasıl söyleyebilirim? bunu ölçecek bir yazılım var mı?

Yanıtlar:


195

Sen var (en azından) iki çözüm:

Oldukça "naif" olan, kodun bir kısmından önce ve sonra, yürütme sırasında ne kadar zaman geçtiğini anlamak için mikro zamanı (doğru) kullanmaktır; diğer cevaplar bunu söyledi ve şimdiden örnekler verdi, bu yüzden daha fazlasını söylemeyeceğim.

Birkaç talimatı karşılaştırmak istiyorsanız, bu iyi bir çözümdür; Örneğin, iki tür işlevi karşılaştırmak gibi - herhangi bir "tedirgin edici öğenin" ortalamasının alındığından emin olmak için binlerce kez yapılması daha iyidir.

Bunun gibi bir şey, bir diziyi serileştirmenin ne kadar sürdüğünü bilmek istiyorsanız:

$before = microtime(true);

for ($i=0 ; $i<100000 ; $i++) {
    serialize($list);
}

$after = microtime(true);
echo ($after-$before)/$i . " sec/serialize\n";

Mükemmel değil, ama kullanışlı ve kurulumu çok zaman almıyor.



Bir komut dosyasının tamamında hangi işlevin çok fazla zaman aldığını belirlemek istiyorsanız oldukça iyi çalışan diğer çözüm, kullanmaktır:

  • Xdebug uzantısı, komut veri profil üretmek için
  • Profilleme verilerini okuyan ve size okunabilir bir şey sunan yazılım. Bunlardan üç tanesini biliyorum:
    • Webgrind ; web arayüzü; herhangi bir Apache + PHP sunucusunda çalışmalıdır
    • WinCacheGrind ; sadece pencerelerde
    • KCacheGrind ; muhtemelen sadece Linux ve linux benzeri; Tercih ettiğim bu, btw

Profil oluşturma dosyalarını almak için Xdebug'u kurmanız ve yapılandırmanız gerekir; belgelerin PHP Scripts Profil Oluşturma sayfasına bir göz atın .

Genelde yaptığım şey, profil oluşturucuyu varsayılan olarak etkinleştirmek değil (oldukça büyük dosyalar oluşturur ve işleri yavaşlatır) , ancak XDEBUG_PROFILEyalnızca ihtiyacım olan sayfa için profil oluşturmayı etkinleştirmek için GET verisi olarak adlandırılan bir parametre gönderme olanağını kullanmaktır .
Php.ini dosyamın profil oluşturma ile ilgili kısmı şuna benzer:

xdebug.profiler_enable = 0              ; Profiling not activated by default
xdebug.profiler_enable_trigger = 1      ; Profiling activated when requested by the GET parameter
xdebug.profiler_output_dir = /tmp/ouput_directory
xdebug.profiler_output_name = files_names

(Daha fazla bilgi için belgeleri okuyun)

Bu ekran görüntüsü KcacheGrind'deki bir C ++ programından alınmıştır: (kaynak: sourceforge.net ) PHP betikleri ile tamamen aynı şeyi elde edeceksiniz ;-) (KCacheGrind ile demek istiyorum; WinCacheGrind, KCacheGrind kadar iyi değildir ... )http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif



Bu, uygulamada zaman gerekenlere güzel bir görünüm almasını sağlar - ve bazen kesinlikle bulmak için yardımcı olur herşey yavaşlattığını işlevi ^^

Xdebug'ın PHP tarafından harcanan CPU süresini saydığını unutmayın; PHP bir Veritabanından yanıt beklerken (örneğin) çalışmıyor; sadece bekliyor. Yani Xdebug, DB isteğinin fazla zaman almadığını düşünecek!
Bunun profili PHP'de değil SQL sunucusunda yapılmalıdır, bu yüzden ...


Umarım bu yardımcı olur :-)
İyi eğlenceler!


1
QCacheGrind'in bir Windows yapısı var :-) sourceforge.net/projects/qcachegrindwin
François Breton

43

Hızlı şeyler için bunu yapıyorum (PHP'de):

$startTime = microtime(true);
doTask(); // whatever you want to time
echo "Time:  " . number_format(( microtime(true) - $startTime), 4) . " Seconds\n";

Ayrıca http://xdebug.org/ gibi bir profil oluşturucu da kullanabilirsiniz .


2
Ek doğruluk için, (a) bir döngü kullanmayı ve zamanın ortalamasını almayı ve (b) test ettiğiniz her şey için ayrı dosyalar kullanmayı öneririm. Bir komut dosyası içinde birkaç zamanlamanız varsa, sıraları bazen bir fark yaratabilir.
DisgruntledGoat

9

Basit bir zamanlama dersi yaptım, belki birisi için yararlıdır:

class TimingHelper {

    private $start;

    public function __construct() {
        $this->start = microtime(true);
    }

    public function start() {
        $this->start = microtime(true);
    }

    public function segs() {
        return microtime(true) - $this->start;
    }

    public function time() {
        $segs = $this->segs();
        $days = floor($segs / 86400);
        $segs -= $days * 86400;
        $hours = floor($segs / 3600);
        $segs -= $hours * 3600;
        $mins = floor($segs / 60);
        $segs -= $mins * 60;
        $microsegs = ($segs - floor($segs)) * 1000;
        $segs = floor($segs);

        return 
            (empty($days) ? "" : $days . "d ") . 
            (empty($hours) ? "" : $hours . "h ") . 
            (empty($mins) ? "" : $mins . "m ") . 
            $segs . "s " .
            $microsegs . "ms";
    }

}

kullanın:

$th = new TimingHelper();
<..code being mesured..>
echo $th->time();
$th->start(); // if it's the case
<..code being mesured..>
echo $th->time();

// result: 4d 17h 34m 57s 0.00095367431640625ms 

echo$echo
Yanlış

9

2020 Güncellemesi

Bu soruları en son yanıtladığımdan bu yana uzun yıllar geçti, bu yüzden bunun APM ortamında bir güncellemeyi hak ettiğini düşündüm.

  • AppDynamics, Cisco tarafından satın alındı ​​ve sundukları sonsuza kadar ücretsiz hesap, web sitelerinden çıkarıldı.
  • NewRelic, APM pazarına yeni gelen ile rekabet edebilmek için fiyatlandırmasını 149 $ / aydan 25 $ / ay / sunucuya düşürdü, Datadog 31 $ / ay / sunucu sunuyor.
  • Datadog APM özellikleri hala hafif ve arzulanan çok şey bırakıyor. Ancak önümüzdeki yıl boyunca bunları geliştirdiğini ve geliştirdiğini görüyorum.
  • Ruxit, Dynatrace tarafından satın alındı. Ruxit eski Dynatrace Çalışanları tarafından yapıldığından burada şok edici bir şey yok. Bu, Dynatrace'in daha iyisi için gerçek bir SaaS modeline dönüşmesine izin verdi. İsterseniz o hantal Java istemcisine veda edin.
  • Artık ücretsiz / açık kaynak seçenekleri de var. Ödeme Apache Skywalking onların üst teknoloji şirketleri arasında Çin'de çok popüler ve PinPoint Eğer yüklemeden önce deneyebileceğiniz bir demo sunuyor. Bunların her ikisi de barındırmayı yönetmenizi gerektirir, bu nedenle birkaç Sanal Makineyi çalıştırmaya hazır olun ve kurulum ve yapılandırma için biraz zaman harcayın.
  • Bu açık kaynaklı APM çözümlerinden hiçbirini denemedim, bu yüzden onları önerecek konumda değilim, ancak, tüm bu APM çözümlerini birden fazla kuruluş için şirket içi veya bulut üzerinde yüzlerce uygulama için dağıtmayı kişisel olarak başardım / microservices. Bu yüzden güvenle söyleyebilirim ki, faturanıza uyuyorlarsa hiçbir satıcıyla yanlış gidemezsiniz.


İlk olarak Ekim 2015'te Cevaplandı

İşte sorunuzun doğrudan cevabı

bunu ölçecek bir yazılım var mı?

Evet var. Neden henüz kimsenin bundan bahsetmediğini merak ediyorum. Yukarıda önerilen cevaplar hızlı bir kontrol için iyi görünse de uzun vadede veya daha büyük bir proje için ölçeklenebilir değildir.

Neden tam olarak bunun için ve çok daha fazlası için oluşturulmuş bir Uygulama Performansı İzleme (APM) aracı kullanmıyorsunuz? Yöntem düzeyine kadar her uygulamanın yürütme süresini, kaynak kullanımını, verimini izlemek için NewRelic, AppDynamics, Ruxit'e (tümü ücretsiz sürümü vardır) göz atın.


6

Bir çerçevenin performansını hızlı bir şekilde test etmek istiyorsanız, index.php dosyasına koyabilirsiniz.

//at beginning
$milliseconds = round(microtime(true) * 1000);

//and at the end
echo round(microtime(true) * 1000) - $milliseconds;

Her seferinde milisaniye cinsinden yürütme süresi alacaksınız . Çünkü mikrosaniyeler, bir çerçeve vakasını test etmede çok faydalı değildir.



4

Sizinle 10 argümana kadar mevcut herhangi bir fonksiyonun hızını ölçmek için kullandığım kendi kendine yapılan bir fonksiyonu paylaşmak istiyorum:

function fdump($f_name='', $f_args=array()){

    $f_dump=array();
    $f_result='';

    $f_success=false;

    $f_start=microtime();
    $f_start=explode(' ', $f_start);
    $f_start=$f_start[1] + $f_start[0];

    if(function_exists($f_name)){

        if(isset($f_args[0])&&is_array($f_args[0])){
            if($f_result=$f_name($f_args)){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[1])){
            if($f_result=$f_name($f_args[0])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[2])){
            if($f_result=$f_name($f_args[0],$f_args[1])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[3])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[4])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[5])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[6])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[7])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[8])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[9])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[10])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8],$f_args[9])){
                $f_success=true;
            }
        }
    }
    $f_end=microtime();
    $f_end=explode(' ', $f_end);
    $f_end=$f_end[1] + $f_end[0];

    $f_time=round(($f_end - $f_start), 4);
    $f_dump['f_success']=$f_success;
    $f_dump['f_time']=$f_time;
    $f_dump['f_result']=$f_result;

    var_dump($f_dump);exit;

    //return $f_result;

}

Misal

function do_stuff($arg1='', $arg2=''){
    return $arg1.' '.$arg2;
}

fdump('do_stuff',array('hello', 'world'));

İadeler

  array(3) {
    ["f_success"]=>
    bool(true)
    ["f_time"]=>
    float(0)            //too fast...
    ["f_result"]=>
    string(11) "hello world"
  }

3

Web bağlamı dışında test edilebilecek bir şeyse, sadece Unix timekomutunu kullanıyorum.


3

Zend Studio, XDebug veya ZendDebugger kullanarak profil oluşturma için yerleşik desteğe sahiptir. Kodunuzun profilini çıkaracak ve size her işlevin tam olarak ne kadar sürdüğünü söyleyecektir. Darboğazlarınızın nerede olduğunu bulmak için harika bir araçtır.


1

Gerekli zamanı hesaplamak için bir işlemden önce ve sonra zaman damgalarını veya mikro zamanı () saklamak gibi temel şeyleri kullanabilirsiniz. Bunu yapmak kolay, ancak çok doğru değil. Belki daha iyi bir çözüm Xdebug'dur , onunla hiç çalışmadım ama bulabildiğim en iyi bilinen PHP hata ayıklayıcı / profilleyici gibi görünüyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.