PHP 魔法函数性能分析 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
TIGERB
V2EX    程序员

PHP 魔法函数性能分析

  •  1
     
  •   TIGERB
    TIGERB 2017-03-05 23:41:25 +08:00 4040 次点击
    这是一个创建于 3220 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    曾经记得鸟哥 Laruence 提过不建议使用"魔术方法",自此之后一旦涉及使用魔术方法的地方,我都会下意识的想一下,这样写真的好吗?由于这一到两年来一直忙于工作和学习新的知识,所以在这道坎儿上一直没有做深入的探索一直恍恍惚惚过去了,今年是我进行深入学习的一年,因此现在必须对这个问题做个了结了。我们先来看看鸟哥 Laruence 博客曾经提到的:

    当我把 PPT 分享给公司的同事的时候, 会有人质疑, 魔术方法都不让用? 优化的建议, 是建议, 是防止大家滥用, 肆无忌惮的用. 如果你能在写代码的时候, 能意识到, 什么慢, 什么快, 从而避免一些没有必要的对魔术方法的调用, 那就是这个优化建议所追求的效果了

    疑惑

    1. 魔术方法真的性能比较差吗?
    2. PHP7 里使用魔术方法的性能还是存在问题吗?
    3. 我们应该如何合理的使用魔术方法?

    方案

    面对我的疑惑,我的方案是:

    • 统计对比使用魔术方法和不使用魔术方法脚本执行的时间差异
    • PHP5.6.26-1 下连续执行脚本 n 次
    • 统计执行时间的平均值 /最小值 /最大值
    • PHP7.0.12-2 下连续执行脚本 n 次
    • 统计执行时间的平均值 /最小值 /最大值

    目前个人能力有限,只能通过这种方式,如果你有更好的方案或者建议可以告诉我,谢谢, haha~

    测试

    __construct

    首先我们先来看看构造函数__construct 的实验, php 脚本如下:

    <?php /** * 魔术方法性能探索 * * 构造函数 * * @author TIGERB <https://github.com/TIGERB> */ require('./function.php'); if (!isset($argv[1])) { die('error: variable is_use_magic is empty'); } $is_use_magic = $argv[1]; /** * 构造函数使用类名 */ class ClassOne { public function classOne() { # code... } } /** * 构造函数使用魔术函数__construct */ class ClassTwo { public function __construct() { # code... } } $a = getmicrotime(); if ($is_use_magic === 'no_magic') { new ClassOne(); }else { new ClassTwo(); } $b = getmicrotime(); echo ($b-$a) . "\n"; 
    • PHP5.6 不使用魔术方法数据如下,单位微秒μm
    // PHP5.6 中连续调用脚本 10000 次 sh test 10000 no_magic php5 construct // 运行数据统计脚本 sh analysis ./logs/__construct_no_magic_php5.log 10000 // 结果 avg: 34μm max: 483μm min: 26μm 
    • PHP5.6 使用魔术方法数据如下,单位微秒μm
    // PHP5.6 中连续调用脚本 10000 次 sh test 10000 magic php5 construct // 运行数据统计脚本 sh analysis ./logs/__construct_magic_php5.log 10000 // 结果 avg: 28μm max: 896μm min: 20μm 
    • PHP7.0 不使用魔术方法数据如下,单位微秒μm
    // PHP7.0 中连续调用脚本 10000 次 sh test 10000 no_magic php construct // 运行数据统计脚本 sh analysis ./logs/__construct_no_magic_php.log 10000 // 结果 avg: 19μm max: 819μm min: 13μm 
    • PHP7.0 使用魔术方法数据如下,单位微秒μm
    // PHP7.0 中连续调用脚本 10000 次 sh test 10000 magic php construct // 运行数据统计脚本 sh analysis ./logs/__construct_magic_php.log 10000 // 结果 avg: 14μm max: 157μm min: 10μm 

    通过上面的数据我们可以看出:

    使用__construct 作为构造函数的脚本执行的平均时间是要快于使用类名作为构造函数的,__大概快 5 到 6 微秒__,不论是在 php5.6 还是 php7.0 中。

    __call

    接着,我们来看看__call 的实验, php 脚本如下:

    <?php /** * 魔术方法性能探索 * * 构造函数 * * @author TIGERB <https://github.com/TIGERB> */ require('./function.php'); if (!isset($argv[1])) { die('error: variable is_use_magic is empty'); } $is_use_magic = $argv[1]; /** * 构造函数使用类名 */ class ClassOne { public function __construct() { # code... } public function test() { # code... } } /** * 构造函数使用魔术函数__construct */ class ClassTwo { public function __construct() { # code... } public function __call($method, $argus) { # code... } } $a = getmicrotime(); if ($is_use_magic === 'no_magic') { $instance = new ClassOne(); $instance->test(); }else { $instance = new ClassTwo(); $instance->test(); } $b = getmicrotime(); echo ($b-$a) . "\n"; 
    • PHP5.6 不使用魔术方法数据如下,单位微秒μm
    // PHP5.6 中连续调用脚本 10000 次 sh test 10000 no_magic php5 call // 运行数据统计脚本 sh analysis ./logs/__call_no_magic_php5.log 10000 // 结果 avg: 27μm max: 206μm min: 20μm 
    • PHP5.6 使用魔术方法数据如下,单位微秒μm
    // PHP5.6 中连续调用脚本 10000 次 sh test 10000 magic php5 call // 运行数据统计脚本 sh analysis ./logs/__call_magic_php5.log 10000 // 结果 avg: 29μm max: 392μm min: 22μm 
    • PHP7.0 不使用魔术方法数据如下,单位微秒μm
    // PHP7.0 中连续调用脚本 10000 次 sh test 10000 no_magic php call // 运行数据统计脚本 sh analysis ./logs/__call_no_magic_php.log 10000 // 结果 avg: 16μm max: 256μm min: 10μm 
    • PHP7.0 使用魔术方法数据如下,单位微秒μm
    // PHP7.0 中连续调用脚本 10000 次 sh test 10000 magic php call // 运行数据统计脚本 sh analysis ./logs/__call_magic_php.log 10000 // 结果 avg: 18μm max: 2459μm min: 11μm 

    通过上面的数据我们可以看出:

    使用__call 的脚本执行的平均时间是要慢于不使用,__大概慢 2 微秒__,不论是在 php5.6 还是 php7.0 中。

    __callStatic

    接着,我们来看看__callStatic 的实验, php 脚本如下:

    <?php /** * 魔术方法性能探索 * * 静态重载函数 * * @author TIGERB <https://github.com/TIGERB> */ require('./function.php'); if (!isset($argv[1])) { die('error: variable is_use_magic is empty'); } $is_use_magic = $argv[1]; /** * 存在 test 静态方法 */ class ClassOne { public function __construct() { # code... } public static function test() { # code... } } /** * 使用重载实现 test */ class ClassTwo { public function __construct() { # code... } public static function __callStatic($method, $argus) { # code... } } $a = getmicrotime(); if ($is_use_magic === 'no_magic') { ClassOne::test(); }else { ClassTwo::test(); } $b = getmicrotime(); echo ($b-$a) . "\n"; 
    • PHP5.6 不使用魔术方法数据如下,单位微秒μm
    // PHP5.6 中连续调用脚本 10000 次 sh test 10000 no_magic php5 callStatic // 运行数据统计脚本 sh analysis ./logs/__callStatic_no_magic_php5.log 10000 // 结果 avg: 25μm max: 129μm min: 19μm 
    • PHP5.6 使用魔术方法数据如下,单位微秒μm
    // PHP5.6 中连续调用脚本 10000 次 sh test 10000 magic php5 callStatic // 运行数据统计脚本 sh analysis ./logs/__callStatic_magic_php5.log 10000 // 结果 avg: 28μm max: 580μm min: 20μm 
    • PHP7.0 不使用魔术方法数据如下,单位微秒μm
    // PHP7.0 中连续调用脚本 10000 次 sh test 10000 no_magic php callStatic // 运行数据统计脚本 sh analysis ./logs/__callStatic_no_magic_php.log 10000 // 结果 avg: 14μm max: 130μm min: 9μm 
    • PHP7.0 使用魔术方法数据如下,单位微秒μm
    // PHP7.0 中连续调用脚本 10000 次 sh test 10000 magic php callStatic // 运行数据统计脚本 sh analysis ./logs/__callStatic_magic_php.log 10000 // 结果 avg: 14μm max: 159μm min: 10μm 

    通过上面的数据我们可以看出:

    在 php5.6 中使用__callStatic 的脚本执行的平均时间是要慢于不使用,__大概慢 3 微秒__;在 php7.0 中使用__callStatic 的脚本执行的平均时间是要大致等于不使用__callStatic 的;

    __set

    接着,我们来看看__set 的实验, php 脚本如下:

    <?php /** * 魔术方法性能探索 * * 设置私有属性__set * * @author TIGERB <https://github.com/TIGERB> */ require('./function.php'); if (!isset($argv[1])) { die('error: variable is_use_magic is empty'); } $is_use_magic = $argv[1]; /** * 实现公共方法设置私有属性 */ class ClassOne { /** * 私有属性 * * @var string */ private $someVariable = 'private'; public function __construct() { # code... } public function setSomeVariable($value = '') { $this->someVariable = $value; } } /** * 使用_set 设置私有属性 */ class ClassTwo { /** * 私有属性 * * @var string */ private $someVariable = 'private'; public function __construct() { # code... } public function __set($name = '', $value = '') { $this->$name = $value; } } $a = getmicrotime(); if ($is_use_magic === 'no_magic') { $instance = new ClassOne(); $instance->setSomeVariable('public'); }else { $instance = new ClassTwo(); $instance-&g;someVariable = 'public'; } $b = getmicrotime(); echo ($b-$a) . "\n"; 
    • PHP5.6 不使用魔术方法数据如下,单位微秒μm
    // PHP5.6 中连续调用脚本 10000 次 sh test 10000 no_magic php5 set // 运行数据统计脚本 sh analysis ./logs/__set_no_magic_php5.log 10000 // 结果 avg: 31μm max: 110μm min: 24μm 
    • PHP5.6 使用魔术方法数据如下,单位微秒μm
    // PHP5.6 中连续调用脚本 10000 次 sh test 10000 magic php5 set // 运行数据统计脚本 sh analysis ./logs/__set_magic_php5.log 10000 // 结果 avg: 33μm max: 138μm min: 25μm 
    • PHP7.0 不使用魔术方法数据如下,单位微秒μm
    // PHP7.0 中连续调用脚本 10000 次 sh test 10000 no_magic php set // 运行数据统计脚本 sh analysis ./logs/__set_no_magic_php.log 10000 // 结果 avg: 15μm max: 441μm min: 11μm 
    • PHP7.0 使用魔术方法数据如下,单位微秒μm
    // PHP7.0 中连续调用脚本 10000 次 sh test 10000 magic php set // 运行数据统计脚本 sh analysis ./logs/__set_magic_php.log 10000 // 结果 avg: 17μm max: 120μm min: 11μm 

    通过上面的数据我们可以看出:

    使用__set 的脚本执行的平均时间是要慢于不使用,__大概慢 2 微秒__,不论是在 php5.6 还是 php7.0 中。

    __get

    接着,我们来看看__get 的实验, php 脚本如下:

    <?php /** * 魔术方法性能探索 * * 读取私有属性__get * * @author TIGERB <https://github.com/TIGERB> */ require('./function.php'); if (!isset($argv[1])) { die('error: variable is_use_magic is empty'); } $is_use_magic = $argv[1]; /** * 实现公共方法获取私有属性 */ class ClassOne { /** * 私有属性 * * @var string */ private $someVariable = 'private'; public function __construct() { # code... } public function getSomeVariable() { return $this->someVariable; } } /** * 使用_get 获取私有属性 */ class ClassTwo { /** * 私有属性 * * @var string */ private $someVariable = 'private'; public function __construct() { # code... } public function __get($name = '') { return $this->$name; } } $a = getmicrotime(); if ($is_use_magic === 'no_magic') { $instance = new ClassOne(); $instance->getSomeVariable(); }else { $instance = new ClassTwo(); $instance->someVariable; } $b = getmicrotime(); echo ($b-$a) . "\n"; 
    • PHP5.6 不使用魔术方法数据如下,单位微秒μm
    // PHP5.6 中连续调用脚本 10000 次 sh test 10000 no_magic php5 get // 运行数据统计脚本 sh analysis ./logs/__get_no_magic_php5.log 10000 // 结果 avg: 28μm max: 590μm min: 20μm 
    • PHP5.6 使用魔术方法数据如下,单位微秒μm
    // PHP5.6 中连续调用脚本 10000 次 sh test 10000 magic php5 get // 运行数据统计脚本 sh analysis ./logs/__get_magic_php5.log 10000 // 结果 avg: 28μm max: 211μm min: 22μm 
    • PHP7.0 不使用魔术方法数据如下,单位微秒μm
    // PHP7.0 中连续调用脚本 10000 次 sh test 10000 no_magic php get // 运行数据统计脚本 sh analysis ./logs/__get_no_magic_php.log 10000 // 结果 avg: 16μm max: 295μm min: 10μm 
    • PHP7.0 使用魔术方法数据如下,单位微秒μm
    // PHP7.0 中连续调用脚本 10000 次 sh test 10000 magic php get // 运行数据统计脚本 sh analysis ./logs/__get_magic_php.log 10000 // 结果 avg: 19μm max: 525μm min: 12μm 

    通过上面的数据我们可以看出:

    在 php5.6 中使用__get 的脚本执行的平均时间是要大致等于不使用__get 的;在 php7.0 中使用__get 的脚本执行的平均时间是要慢于不使用,__大概慢 3 微秒__。

    结语

    这里主要测试了__construct(), __call(), __callStatic(), __get(), __set()这五个常用的且可有其他实现方式代替的魔法函数。通过上面的测试再回来解答我的疑惑

    1. 魔术方法真的性能比较差吗?

    答:除了使用__construct 之外,这里使用其他的魔法方法的时间大致慢 10 微妙以内。

    1. PHP7 里使用魔术方法的性能还是存在问题吗?

    答:在 PHP7 中使用与不使用魔术方法之间的差异和在 PHP5.6 中近乎一致。

    1. 我们应该如何合理的使用魔术方法?

    答:通过整个测试我们可以看出使不使用魔法方法这之间的执行时间差异大致都是在 10 微妙以内的,所以如果魔法方法可以很好的节省我们的开发成本和优化我们的代码结构,我们应该可以考虑牺牲掉这不到 10 微妙。而__construct 是要快的,所以使用__construct 应该没什么异议。

    脚本源码

    https://github.com/TIGERB/easy-tips/tree/master/php/magic-function

    第 1 条附言    2017-03-06 10:14:19 +08:00

    纠正

    单位错误:纠正μm 为 μs

    文字错误:微妙为微秒

    函数使用不当:microtime()支持float 传参 true

    27 条回复    2017-03-08 11:42:18 +08:00
    fatjiong
        1
    fatjiong  
       2017-03-05 23:49:43 +08:00
    支持分享。
    TIGERB
        2
    TIGERB  
    OP
       2017-03-05 23:50:58 +08:00
    @fatjiong THX ~ 也希望大家帮我督错~
    gouchaoer
        3
    gouchaoer  
       2017-03-06 00:01:57 +08:00 via Android
    很不错的尝试,不过你测试方法有点问题,我们知道 php-cli 启动后会做很多准备工作,实际上测试逻辑占了很少时间。你可以在 php 内部 loop 很多次
    TIGERB
        4
    TIGERB  
    OP
       2017-03-06 00:16:20 +08:00
    @gouchaoer thx~
    xiaoshangmin
        5
    xiaoshangmin  
       2017-03-06 01:22:49 +08:00 via iPhone
    厉害了我滴哥
    Sunyanzi
        6
    Sunyanzi  
       2017-03-06 01:29:32 +08:00
    脚本欠严谨 ... 不过还是赞这个测试的态度 ...

    顺便指个问题 ... 微秒是 μs 不是 μm ... 另外 microtime 支持传入一个参数你可以看看 ...
    fuxkcsdn
        7
    fuxkcsdn  
       2017-03-06 09:01:25 +08:00 via iPhone
    microtime(true), php 内部循环就好

    p.s.实际上想当然也是魔术方法慢,用魔术方法肯定会多几个判断的
    cenxun
        8
    cenxun  
       2017-03-06 09:05:39 +08:00
    赞一个,有图表就更溜了 ~~
    wyntau
        9
    wyntau  
       2017-03-06 09:38:24 +08:00
    厉害了~
    vus520
        10
    vus520  
       2017-03-06 10:06:26 +08:00
    666
    TIGERB
        11
    TIGERB  
    OP
       2017-03-06 10:07:33 +08:00
    @fuxkcsdn
    @Sunyanzi thx~ 学习了,哈哈~
    TIGERB
        12
    TIGERB  
    OP
       2017-03-06 10:08:02 +08:00
    @Jeremial 文豪威武~
    Felldeadbird
        13
    Felldeadbird  
       2017-03-06 10:08:10 +08:00
    支持楼主。不过除了执行速度问题外,不推荐用魔术方法主要是 由于 魔术方法容易改变 类中属性,或者说 埋下一些 很难调试的坑。
    不过呢,也不是说不能用。合理使用就没问题了。
    TIGERB
        14
    TIGERB  
    OP
       2017-03-06 10:08:31 +08:00
    @vus520 thx~
    TIGERB
        15
    TIGERB  
    OP
       2017-03-06 10:09:21 +08:00
    @cenxun 不错的提议,后续加上, thx~
    TIGERB
        16
    TIGERB  
    OP
       2017-03-06 10:25:10 +08:00
    @Felldeadbird thx~

    我的一些愚见,哈哈:如果完全符合面向对象的编程,类内部的属性是不应该直接暴露出去的,要符合闭原则,但是往往我们的实际编程中是有这个需求的,我们通常的做法可以:
    1. 设置属性为 public => 不符合面向对象设计原则
    2. 实现一个修改私有属性的 public 方法 => 不够统一

    但是__get,__set 其实就是实现统一可控
    peinhu
        17
    peinhu  
       2017-03-06 11:40:07 +08:00
    技术好文要顶!但是有个疑问,为什么 max 和 min 相差这么多?是不是你开启了 opcache 的缘故,测试前做个预热比较好。
    TIGERB
        18
    TIGERB  
    OP
       2017-03-06 11:46:54 +08:00
    @peinhu thx~ 是没进行预热,学习了

    我估计,可能是加载 PHP 解析器出现抖动了吧~
    baizhebz
        19
    baizhebz  
       2017-03-06 12:13:25 +08:00
    Laravel 里有不少对__call()的应用。
    TIGERB
        20
    TIGERB  
    OP
       2017-03-06 14:41:02 +08:00
    @baizhebz 所以 laravel 是个很优雅的框架,哈哈~
    iminto
        21
    iminto  
       2017-03-06 21:16:53 +08:00
    瞎扯淡。。。
    快 5 到 6 微秒。。。咋不说快 5 到 6 纳秒,皮秒呢
    TIGERB
        22
    TIGERB  
    OP
       2017-03-06 23:02:03 +08:00
    @iminto 只是因为鸟哥曾对使用魔法方法的建议,我自己想看看这之间真正的差异而已,结果快了慢了多少都不是目的,了结了我曾经心头的疑虑才是目的。
    iminto
        23
    iminto  
       2017-03-07 16:27:24 +08:00
    @TIGERB 几微秒的差距,有误差和预热的存在,你的测试结果没有意义。还有某鸟这句话是 10 年前说的吧,你现在来测这个问题也没有意义。
    当然,你就是只是了结曾经心头的疑虑。
    TIGERB
        24
    TIGERB  
    OP
       2017-03-07 17:15:33 +08:00
    @iminto 是啊~
    gouchaoer
        25
    gouchaoer  
       2017-03-08 11:30:12 +08:00
    这个文章发的到处都是了, 3L 提的那个你怎么还没改,我根据你的代码测出来效果刚好相反, magic 方法比一般方法慢一倍:

    ```
    <?php
    /**
    * 魔术方法性能探索
    *
    * 构造函数
    *
    * @author TIGERB <https://github.com/TIGERB>
    */

    if (!isset($argv[1])) {
    die('error: variable is_use_magic is empty');
    }
    $is_use_magic = $argv[1];

    /**
    * 构造函数使用类名
    */
    class ClassOne
    {
    public function __construct()
    {
    # code...
    }

    public function test()
    {
    $i=0;
    $i++;
    $arr=[];
    $arr['test']=1;
    # code...
    }
    }

    /**
    * 构造函数使用魔术函数__construct
    */
    class ClassTwo
    {
    public function __construct()
    {
    # code...
    }

    public function __call($method, $argus)
    {
    $i=0;
    $i++;
    $arr=[];
    $arr['test']=1;

    # code...
    }
    }

    $a = microtime(true);
    if ($is_use_magic === 'no_magic') {
    echo "no_magic\n";
    $instance = new ClassOne();
    for($i=0;$i<10000000;$i++)
    $instance->test();
    }else {
    echo "magic\n";
    $instance = new ClassTwo();
    for($i=0;$i<10000000;$i++)
    $instance->test();
    }
    $b = microtime(true);

    echo ($b-$a) . "\n";


    ```

    [root@iZ239ui2iq8Z luminati-proxy-solution]# php56 test.php no_magic
    no_magic
    3.8641951084137
    [root@iZ239ui2iq8Z luminati-proxy-solution]# php56 test.php magic
    magic
    7.3454520702362
    [root@iZ239ui2iq8Z luminati-proxy-solution]# php70 test.php no_magic
    no_magic
    1.3668580055237
    [root@iZ239ui2iq8Z luminati-proxy-solution]# php70 test.php magic
    magic
    2.172700881958
    gouchaoer
        26
    gouchaoer  
       2017-03-08 11:36:03 +08:00
    构造函数方法测出来和你的结论是一致的:
    ```
    <?php
    /**
    * 魔术方法性能探索
    *
    * 构造函数
    *
    * @author TIGERB <https://github.com/TIGERB>;
    */

    if (!isset($argv[1])) {
    die('error: variable is_use_magic is empty');
    }
    $is_use_magic = $argv[1];

    /**
    * 构造函数使用类名
    */
    class ClassOne
    {
    public function classOne()
    {
    # code...
    }
    }

    /**
    * 构造函数使用魔术函数__construct
    */
    class ClassTwo
    {
    public function __construct()
    {
    # code...
    }
    }

    $a = microtime(true);
    if ($is_use_magic === 'no_magic') {
    echo "no_magic\n";

    for($i=0;$i<10000000;$i++)
    $instance = new ClassOne();
    }else {
    echo "magic\n";

    for($i=0;$i<10000000;$i++)
    $instance = new ClassTwo();
    }
    $b = microtime(true);

    echo ($b-$a) . "\n";


    ```

    [root@iZ239ui2iq8Z luminati-proxy-solution]# php56 test2.php no_magic
    no_magic
    2.2117800712585
    [root@iZ239ui2iq8Z luminati-proxy-solution]# php56 test2.php magic
    magic
    2.1968791484833
    [root@iZ239ui2iq8Z luminati-proxy-solution]# php70 test2.php no_magic
    no_magic
    1.2584509849548
    [root@iZ239ui2iq8Z luminati-proxy-solution]# php70 test2.php magic
    magic
    1.2768771648407
    TIGERB
        27
    TIGERB  
    OP
       2017-03-08 11:42:18 +08:00
    @gouchaoer 我求的是使用不使用之间的时间差值,并且跑了 10000 次,加载 php-cli 时间抖动的应该是影响不大了吧, php 内部 loop 我之前试过发现有些不对劲,我再试试。 thx~
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5365 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 49ms UTC 08:42 PVG 16:42 LAX 00:42 JFK 03:42
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86