I have a piece of python code doing fuzzy matching which works very well and is pretty fast. For reference, it uses the following files:
https://raw.githubusercontent.com/datasets/s-and-p-500-companies/master/data/constituents.csv https://raw.githubusercontent.com/nlintz/pyBros/master/sp500/sp500.csv
import csv
from fuzzywuzzy import process
def csv_reader(file, key):
with open(file) as csvfile:
reader = csv.DictReader(csvfile)
return [row[key] for row in reader]
const_data = csv_reader("constituents.csv", "Name")
target_data = csv_reader("sp500.csv", "company")
with open('results_python.csv', 'w', newline='') as csvfile:
fieldnames = ["name", "match_name", "match_score"]
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for row in const_data:
match = process.extractOne(row, target_data)
writer.writerow({'name': row, 'match_name': match[0], 'match_score': match[1]})
This is how it performs:
$ time ./fuzzy.py
./fuzzy.py 19,90s user 0,13s system 97% cpu 20,444 total
However, my surprise came when I did a pretty similar code in Golang using a port of the fuzzywuzzy
library. I want to understand if the slowness of it is related to the way I structure my code, or some deeper reason within the matching library.
package main
import (
"encoding/csv"
"os"
"strconv"
"github.com/paul-mannino/go-fuzzywuzzy"
)
func readCsv(file string) [][]string {
csvFile, _ := os.Open(file)
defer csvFile.Close()
r := csv.NewReader(csvFile)
records, _ := r.ReadAll()
return records
}
func main() {
original:= readCsv("constituents.csv")
target:= readCsv("sp500.csv")
csvOut, _ := os.Create("results_go.csv")
csvwriter := csv.NewWriter(csvOut)
var targetData []string
for _, line := range target[1:] {
targetData = append(targetData, line[1])
}
csvwriter.Write([]string{"name", "match_name", "match_score"})
for _, line := range original[1:] {
match, _ := fuzzy.ExtractOne(line[1], targetData)
csvwriter.Write([]string{line[1], match.Match, strconv.Itoa(match.Score)})
}
}
This is how the Go version performs:
$ time ./fuzzy
./fuzzy 75,04s user 1,28s system 98% cpu 1:17,51 total
Are there any possible bad steps that I took in my Go code that made this comparison slow? Are there any improvements you could suggest to make it perform at the very least to a similar speed as the python code?