开发者社区> 问答> 正文

Go在大文件读取为什么耗费时间是PHP3倍?报错

一个文件。13G。逐行读取,将读取到的内容按空格切割为数组,取数组中Key=8的值累加。最后得到这个累加的值。


很简单的文件处理程序。Go和PHP都是单线程顺序执行。


我用Go跑了一遍6分30秒,我又用PHP跑了一遍是2分30秒。


虽然PHP是最好的语言,但是Go作为编译型强类型语言,在我的认知里要比PHP快得多才对,为什么会出现这样的结果?

补充:Go用了300秒,PHP5.6用了200秒,PHP7用了47秒。我是真的不敢相信这就是Google大力推广的Go。我宁愿相信这是我代码的问题。


代码上其实真没什么东西,就是打开文件、逐行读取、按空格切割为数组、取数组第9个字段,累加求和


GO代码:


package main
import (
	"fmt"
	"os"
	"strings"
	"bufio"
	"io"
	"strconv"
	"time"
)

func main(){
	startTime := time.Now().UnixNano()
	path := "./"
	//读取文件
	var filenameList = []string{"cdn.log"}
	//解析
	for _, file := range filenameList{
		parseFile(path, file)
	}
	endTime := time.Now().UnixNano()
	fmt.Println(endTime-startTime)
}

func parseFile(path, file string){
	filePath := path + file
	f, err := os.Open(filePath)
	defer f.Close()
	if err != nil {
		fmt.Println("打开文件失败:"+filePath)
		os.Exit(1)
	}
	//错误信息
	var errList []error
	//总流量
	var totalSize uint64
	//过滤流量
	var keepStoppSize int64

	var errMsg error
	var line []byte
	var content string
	var size int64
	var lineNum int64 = 0

	bfRd := bufio.NewReader(f)
	for {
		lineNum += 1
		line, errMsg = bfRd.ReadBytes('\n')
//		line, _, errMsg = bfRd.ReadLine()

		//判断是否结尾
		if errMsg == io.EOF {
			resultFilePath := path + "/result_" + file + ".out"
			resultFileHandle, err := os.OpenFile(resultFilePath, os.O_CREATE | os.O_WRONLY, 0755)
			if err != nil{
				fmt.Println(err)
			}
			defer resultFileHandle.Close()
			resultFileHandle.WriteString("TotalSize:" + strconv.Itoa(int(totalSize)) + "\r\n")
			resultFileHandle.WriteString("KeepStoppSize:" + strconv.Itoa(int(keepStoppSize)) + "\r\n")
			return
		}

		content = string(line)
		slice := strings.Fields(content)
		size, _ = strconv.ParseInt(slice[8], 10, 0)
		if strings.Contains(slice[5], "keep_stopp=on") {
			keepStoppSize += size
			continue
		}
		totalSize += uint64(size)

		if errMsg != nil {
			errList = append(errList, errMsg)
			continue
		}
	}
}


PHP代码:

<?php
date_default_timezone_set('Asia/Shanghai');

echo "任务开始:".$start."\n\n";

$fileList = array("cdn_qihu360_2015111215.log");

$bd = array();
$allTotalSize = 0;
foreach($fileList as $file){
    if(!file_exists($file)){
        continue;
    }
    $handle = fopen($file, 'r');
    $total_size = 0;
    while(!feof($handle)){
        $line = trim(fgets($handle));
        if(strlen($line) < 5){
            continue;
        }
        if(preg_match("/keep_stopp=on/", $line)){
            continue;
        }
        $tmp_arr = explode(' ', $line);
        $size = intval($tmp_arr[8]);
        $total_size += $size;
    }
    echo $file . ':  ' . $total_size."\n";
    $allTotalSize += $total_size;
}

展开
收起
一枚小鲜肉帅哥 2020-06-20 21:08:25 2848 0
1 条回答
写回答
取消 提交回答
  • 菜不可及的程序猿

    对 go 不了解 。

    看代码 。貌似 是 你的 go 遍历的 13g 的每一个 字符 ,

    而php 可以用 fgets 直接读取一行 。估计就是 C的 fgets 的包装 ,性能高。

    应该是 这个造成的差距

    2020-06-20 21:09:10
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
Go语言路上踩过的坑 立即下载
gohbase :HBase go客户端 立即下载
Go构建日请求千亿级微服务实践 立即下载