Почему myVar = strings.Fields (scanner.Text ()) занимает гораздо больше времени, чем сопоставимая операция в python? - PullRequest
0 голосов
/ 12 июня 2018

Рассмотрим следующий код в golang

now := time.Now()
sec1 := now.Unix()

file, err := os.Open(file_name)
if err != nil {
    log.Fatal(err)
}
defer file.Close()

scanner := bufio.NewScanner(file)

var parsedLine []string

for scanner.Scan() {
    parsedLine = strings.Fields(scanner.Text())
}

fmt.Println(parsedLine)
now2 := time.Now()
sec2 := now2.Unix()
fmt.Println(sec2 - sec1) // takes 24 second for file1.txt

И рассмотрим эту программу на python

start = time.time()

with open(file) as f:
    for line in f:
        parsedLine = line.split()

end = time.time() 
print end - start # takes 4.6450419426 second for file1.txt

Я вижу, что программа golang в 5 раз медленнее, чем программа на python в MacBook Pro

В частности, эта строка

parsedLine = strings.Fields(scanner.Text())

очень медленная.

Если я изменю эту строку в golang на

if strings.Contains(scanner.Text(), "string_that_never_exist") {
     continue
}
// take less than 1 second

и Python на

if "string_that_never_exist" in line:
    continue
# takes 2.86928987503 second

Версия Golang теперь намного быстрее, чем версия Python.

Я немного озадачен, почему strings.Fields(scanner.Text()) может быть медленнее, чем line.split()

Я чувствую, что мне не хватаетчто-то глупое, может кто-нибудь указать мне, почему версия golang занимает больше времени, чем python

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Любой эталон должен быть хорошим научным экспериментом.Он должен быть воспроизводимым.

Сначала определите легкодоступный ввод:

Полное собрание сочинений Уильяма Шекспира Уильяма Шекспира:

http://www.gutenberg.org/files/100/100-0.txt

Далее полностью определите исполняемые программы:

linesplit.py:

import time; 
start = time.time()

# http://www.gutenberg.org/files/100/100-0.txt
file = "/home/peter/shakespeare.100-0.txt"
with open(file) as f:
    for line in f:
        parsedLine = line.split()

end = time.time() 
print (end - start)

linesplit.go:

package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
    "strings"
    "time"
)

func main() {
    now := time.Now()
    sec1 := now.Unix()

    // http://www.gutenberg.org/files/100/100-0.txt
    file_name := "/home/peter/shakespeare.100-0.txt"
    file, err := os.Open(file_name)
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)

    var parsedLine []string

    for scanner.Scan() {
        parsedLine = strings.Fields(scanner.Text())
    }

    fmt.Println(parsedLine)
    now2 := time.Now()
    sec2 := now2.Unix()
    fmt.Println(sec2 - sec1) // takes 24 second for file1.txt
    fmt.Println(time.Since(now))
}

Затем предоставьте результаты теста:

$ python2 --version
Python 2.7.14
$ time python2 linesplit.py
.07024809169769
real    0m0.089s
user    0m0.089s
sys     0m0.000s

$ python3 --version
Python 3.6.3
$ time python3 linesplit.py
0.12172794342041016
real    0m0.159s
user    0m0.155s
sys     0m0.004s

$ go version
go version devel +39ad208c13 Tue Jun 12 19:10:34 2018 +0000 linux/amd64
$ go build linesplit.go && time ./linesplit
[]
1
91.833622ms
real    0m0.100s
user    0m0.094s
sys     0m0.004s

$ 

У нас есть Python2

0 голосов
/ 12 июня 2018

Вы используете Unicode в Go и байтовые строки в Python.Ваш код Python выполняет намного более простую задачу, поскольку он не должен выполнять декодирование Unicode или обрабатывать все значения пробелов Unicode.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...