zoukankan      html  css  js  c++  java
  • 地区配置文件的优化

    前些阵子写过一个针对地区配置文件的优化,今天有同事提起,特写下来共同交流!
    问题描述:部分应用需要展示多个企业的地区信息,但从数据库或缓存读到的是一堆地区ID,无法直接显示,需要读地区配置文件将ID转换为地区名; 而地区配置(area.php)文件较大(122K),每次载入文件会耗费7ms左右时间(正常SQL读数据库才耗费不到1ms时间,这个耗费5ms,简直无法忍受)
    解决办法:将地区配置的php文件转换为纯文本文件,每次只读需要的行,不用读全部行;时间复杂度为:O(1)
    使用到的函数: fopen,fseek, fread
    具体的实现过程:
    第一步:将地区配置文件转换为文本文件
       1:将省、市、区的关联数组补全,如市的数组为:

    array('1' => '上海市', '3' => '北京市', '4' => '郑州')
    

       补全后变为:

    array('1' => '上海市', '2' => '', '3' => '北京市', '4' => '郑州')
    

     2:将省市区的名称依次写入文本、一行一个
            书写的格式:

    行号   省、市、区名
    1            北京                                   
    2            上海                                       
    3            天津
    4            重庆
    5            香港
    .             .
    .             .
    .             .
    35          上海
    36      
    37          北京
    38          郑州 
    .            .
    .            .
    753      ID为1的县名称
    754      ID为2的县名称
    755      ID为3的县名称
    .           .
    .           .
    .           .
    

      此时省、市、区的ID与行号就会有如下的关联:

    省:lineid = ID
    市:lineid = ID + 34
    区:lineid = ID + 34 + 718
    

      至此,我们可以根据一个省、市、区的ID获取一个行号,然后用fread读这一行就可以获取到想要的结果;

    第二步:优化第一步结构,并从文本中读数据
         完成第一步之后,就开始翻手册来查找读文件指定行内容的函数,找了很久,遗憾的发现竟然没有这个函数,那真是万念俱灰呀,又瞎搞了。
          一袋烟功夫后,终于想明白了,文件嘛,肯定是存磁盘的,你让它读第100行的内容,它也不知道100行的磁盘"偏移量"是多少,不能一下子读出来也是理所当然;至此,突然恍然大悟,如果第100行的磁盘“偏移量”是固定值,那么直接读出来应该不是问题。哈,很简单嘛,把每行的字节数设为固定值(假设每行48个字节,不足48的填空白字符),第N行的“偏移量”也就固定了。如:读100行的的内容,直接用fseek函数将文件内部指针移动到100 * 48位置,然后用fread函数读一行内容即可。
          功能已基本搞定;使用到的函数有:fopen,fseek,fread;

    第三步:程序的几点优化

      字符写文件时,使用pack函数将字符转为固定字节长度;对每行写入的内容优化:省名称行不变,市名称行除存储市名称外追加所属省的信息,县名称行追加市、省信息;此时,省名称行固定长度48字节,市行固定长度96,区行固定长度144;将省、市、区各部分每行的长度,省、市、区的数量信息存到文件的第一行;查询的类使用单例模式,对查询过的ID存储防止重复查询;

    文件存储格式变为:

    0       第一行存储基本信息,如省的数量,省名称每行占的字节数等;
    1       北京*******                                  
    2       上海*******                                     
    3       天津*******
    4       重庆*******
    5       香港*******
    .           .
    .           .
    .           .
    35      上海,上海*****************
    36      *************************
    37      北京,北京*****************
    38      郑州,河南*****************
    .        .
    .        .
    .        .
    753     ID为1的县名称,ID为1县所在市,所在省名称***********
    754     ID为2的县名称,ID为2县所在市,所在省名称***********
    755     ID为3的县名称,ID为3县所在市,所在省名称***********
    .        .
    .        .
    .        .
    

      

    性能测试
    代码:

    <?php
    include"Area.php";
    //随机生成20个ID
    for($i = 1; $i < 20000; $i++) {
            $id[] = rand(1,3000);
    }
    $stime = microtime(true);
    foreach($id as $v) {
            $info = Xz_Area::getInstance()->getAreaNav($v, 'area');
    }
    $etime = microtime(true);
    echo "
     spend time:". (($etime - $stime) * 1000)."ms
    ";
    

    结果:普通硬盘平均执行时间为0.5ms; Ssd盘平均执行时间在0.3ms以内

  • 相关阅读:
    vscode的go环境配置
    百度过的问题
    javascript判定两个对象是否相等
    chattr
    kubernetes ingress example
    docker 免 sudo
    build local kubernetes env
    go channel
    rpm install and uninstall
    fluentd v0.12 gem install fluent-plugin-webhdfs error
  • 原文地址:https://www.cnblogs.com/dormscript/p/4787518.html
Copyright © 2011-2022 走看看