Pourquoi la lecture et l'écriture de fichiers en Go sont-elles beaucoup plus lentes qu'en Perl ? Il s'agit d'un problème courant que de nombreux développeurs rencontrent lorsqu'ils utilisent ces deux langages de programmation. Dans cet article, l'éditeur PHP Strawberry répondra à cette question pour vous. Lorsque nous comparons la vitesse de lecture et d'écriture de fichiers entre Go et Perl, nous devons prendre en compte deux facteurs clés : les fonctionnalités du langage et l'implémentation sous-jacente. La philosophie de conception du langage Go en termes de lecture et d'écriture de fichiers est différente de celle de Perl, ce qui entraîne des différences de performances. Dans le même temps, la mise en œuvre sous-jacente est également un facteur important affectant la vitesse de lecture et d’écriture. Ensuite, nous analyserons ces facteurs en détail pour vous aider à mieux comprendre pourquoi la lecture et l'écriture de fichiers en Go sont beaucoup plus lentes qu'en Perl.
J'utilise go pour améliorer l'efficacité du code, mais lorsque j'utilise go pour lire et écrire des fichiers, je trouve que son efficacité en lecture et en écriture n'est pas aussi élevée que celle de Perl. Est-ce un problème avec mon code ou d'autres raisons ?
Construire le fichier d'entrée :
# input file: for i in $(seq 1 600000) do echo server$((random%800+100)),$random,$random,$random >> sample.csv done
Lire et écrire des fichiers en utilisant Perl :
time cat sample.csv | perl -ne 'chomp;print"$_"' > out.txt
real 0m0.249s user 0m0.083s sys 0m0.049s
Utilisez go pour lire et écrire des fichiers :
package main import ( "bufio" "fmt" "io" "os" "strings" ) func main() { filepath := "./sample.csv" file, err := os.openfile(filepath, os.o_rdwr, 0666) if err != nil { fmt.println("open file error!", err) return } defer file.close() buf := bufio.newreader(file) for { line, err := buf.readstring('\n') line = strings.trimspace(line) fmt.println(line) if err != nil { if err == io.eof { fmt.println("file read ok!") break } else { fmt.println("read file error!", err) return } } } }
Puis je cours :
time go run read.go > out.txt
real 0m2.332s user 0m0.326s sys 0m2.038s
Pourquoi la vitesse de lecture et d'écriture de Go est-elle près de 10 fois plus lente que celle de Perl ?
Vous comparez des pommes avec des oranges.
Il y a au moins deux erreurs de méthode :
Votre mantra Perl mesure cat
如何读取文件并通过 pipe(2) 发送其内容
,而 perl
lit les données à partir de là, les traite et écrit les résultats sur sa sortie standard.
Votre sort Go
fmt.print*
appels) lors de l'écriture sur la sortie standard à partir du code Perl - citant les docs - "Si la sortie est vers un terminal, la mise en mémoire tampon de ligne est généralement possible, sinon la mise en mémoire tampon de bloc est possible."
Tout d’abord, voici une implémentation go similaire :
package main import ( "bufio" "bytes" "fmt" "os" ) func main() { in := bufio.newscanner(os.stdin) out := bufio.newwriter(os.stdout) for in.scan() { s := bytes.trimspace(in.bytes()) if _, err := out.write(s); err != nil { fmt.fprint(os.stderr, "failed to write file:", err) os.exit(1) } } if err := out.flush(); err != nil { fmt.fprint(os.stderr, "failed to write file:", err) os.exit(1) } if err := in.err(); err != nil { fmt.fprint(os.stderr, "reading failed:", err) os.exit(1) } }
Enregistrons-le sous
et mesurons-le :
chomp.go
$ go build chomp.go
$ for i in $(seq 1 600000);执行 echo server$((random%800+100)),$random,$random,$random;完成 >sample.csv
$ time { perl -ne 'chomp; print "$_";' <sample.csv >out1.txt; } real 0m0.226s user 0m0.102s sys 0m0.048s
$ time { perl -ne 'chomp; print "$_";' <sample.csv >out1.txt; } real 0m0.123s user 0m0.090s sys 0m0.033s
Remarquez comment le temps d'exécution est réduit.
$ time { ./chomp <sample.csv >out2.txt; } real 0m0.063s user 0m0.032s sys 0m0.032s
Assurez-vous que les résultats sont les mêmes :
$ cmp out1.txt out2.txt
linux/amd64
Eh bien, je dois également souligner que pour obtenir des résultats raisonnables, vous devrez exécuter chaque commande, disons 1 000 fois, faire la moyenne des résultats dans chaque lot, puis comparer les chiffres, mais je pense que cela suffit pour prouver ce que vous êtes. Le problème avec la méthode est.
Encore une chose à considérer : le temps d'exécution de ces deux programmes est largement dominé par les E/S du système de fichiers, donc si vous pensez que cela sera plus rapide, vos attentes sont infondées : ces deux programmes sont volumineux Une partie du temps
dormir dans le système du noyau appelle read(2)
et write(2 )
. Un programme go peut être plus rapide qu'un programme Perl dans certains cas impliquant des opérations CPU (surtout s'il est écrit pour tirer parti d'un système multicœur), mais ce n'est pas du tout le cas avec votre exemple. read(2)
和 write(2)
Oh, juste pour que ce soit clair : même si la spécification du langage go ne dit pas
, et go run
est un hack pour des concerts ponctuels et ponctuels, pas travail sérieux, il n’exécute pas non plus de code d’une complexité sérieuse. En bref, go-that-you-are-use n'est pas un langage interprété, bien que la disponibilité de go run
puisse le faire paraître tel. En effet, il fait ce que go build
normal ferait, puis exécute l'exécutable résultant, puis le supprime. go run
是一种针对一次性一次性演出的 hack,不严肃的工作,也不执行任何严重复杂程度的代码。简而言之,go-that-you-are-using 并不是一种解释性语言,尽管 go run
的可用性可能使它看起来如此。事实上,它执行正常 go build
Vous pourriez être tenté de dire que Perl gère également le "code source", mais l'interpréteur Perl est hautement optimisé pour la gestion des scripts et la chaîne d'outils de construction de Go - tout en étant incroyablement rapide par rapport à la plupart des autres langages compilés - n'est pas conçue pour cela. optimisé.
La différence la plus évidente est peut-être que l'interpréteur Perl interprètevotre script (très simple), alors que chomp
和 print
是所谓的“内置函数”,很容易提供给由解释器执行脚本。与构建 go 程序相比,编译器解析源代码文件并将其转换为机器代码,链接器实际上读取 go 标准库的编译包的文件 - 所有这些都是 import
ed, - 从它们,组合所有这些机器代码并写出一个可执行图像文件(这很像 perl
le binaire lui-même ! ); bien sûr, il s’agit d’un processus très consommateur de ressources et n’a rien à voir avec l’exécution réelle du programme.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!