Die effiziente Verarbeitung großer CSV-Dateien ist eine häufige Anforderung in vielen Anwendungen, von der Datenanalyse bis hin zu ETL-Prozessen (Extrahieren, Transformieren, Laden). In diesem Artikel möchte ich die Leistung von vier beliebten Programmiersprachen – Golang, NodeJS mit NestJS, PHP und Python – bei der Verarbeitung großer CSV-Dateien auf einem MacBook Pro M1 vergleichen. Mein Ziel ist es herauszufinden, welche Sprache die beste Leistung für diese Aufgabe bietet.
Hardware: MacBook Pro M1, 256 GB SSD, 8 GB RAM
Software:
Ich habe eine synthetische CSV-Datei namens sales_data.csv mit etwa 1 Million Zeilen verwendet, von denen jede Transaktionsdetails wie Transaktions-ID, Produkt-ID, Menge, Preis und Zeitstempel enthält.
Für jede Sprache führt das Skript die folgenden Aufgaben aus:
Hier sind die Skripte, die für jede Sprache verwendet werden:
sales.go
package main import ( "encoding/csv" "fmt" "os" "strconv" "time" ) func main() { start := time.Now() file, err := os.Open("../generate-csv/sales_data.csv") if err != nil { fmt.Println("Error:", err) return } defer file.Close() reader := csv.NewReader(file) _, _ = reader.Read() // Skip header totalSales := 0.0 productSales := make(map[string]float64) for { line, err := reader.Read() if err != nil { break } productID := line[1] quantity, _ := strconv.Atoi(line[2]) price, _ := strconv.ParseFloat(line[3], 64) total := float64(quantity) * price totalSales += total productSales[productID] += total } var topProduct string var topSales float64 for product, sales := range productSales { if sales > topSales { topProduct = product topSales = sales } } elapsed := time.Since(start) fmt.Printf("Golang Execution time: %s\n", elapsed) fmt.Printf("Total Sales: $%.2f\n", totalSales) fmt.Printf("Top Product: %s with sales $%.2f\n", topProduct, topSales) }
csv.service.ts
import { Injectable } from '@nestjs/common'; import * as fs from 'fs'; import * as fastcsv from 'fast-csv'; // path file CSV const GLOBAL_CSV_PATH = '../generate-csv/sales_data.csv'; @Injectable() @Injectable() export class CsvService { async parseCsv(): Promise<{ nestExecutionTime: number; totalSales: number; topProductSales: number; }> { return new Promise((resolve, reject) => { const startTime = process.hrtime(); let totalSales = 0; const productSales: { [key: string]: number } = {}; fs.createReadStream(GLOBAL_CSV_PATH) .pipe(fastcsv.parse({ headers: true, delimiter: ',' })) .on('data', (row) => { const productID = row.product_id; const quantity = parseInt(row.quantity, 10); const price = parseFloat(row.price); const total = quantity * price; totalSales += total; if (!productSales[productID]) { productSales[productID] = 0; } productSales[productID] += total; }) .on('end', () => { const topProduct = Object.keys(productSales).reduce((a, b) => productSales[a] > productSales[b] ? a : b, ); const topProductSales = productSales[topProduct] || 0; const endTime = process.hrtime(startTime); const nestExecutionTime = endTime[0] + endTime[1] / 1e9; console.log(`NestJS Execution time: ${nestExecutionTime} seconds`); console.log(`Total Sales: $${totalSales}`); console.log( `Top Product: ${topProduct} with sales $${topProductSales}`, ); resolve({ nestExecutionTime, totalSales, topProductSales, }); }) .on('error', (error) => reject(error)); }); } }
csv.controller.ts
import { Controller, Get } from '@nestjs/common'; import { CsvService } from './csv.service'; @Controller('csv') export class CsvController { constructor(private readonly csvService: CsvService) {} @Get('parse') async parseCsv(): Promise<{ nestExecutionTime: number; totalSales: number; topProductSales: number; }> { return this.csvService.parseCsv(); } }
sales.php
<?php $start_time = microtime(true); $file = fopen("../generate-csv/sales_data.csv", "r"); $total_sales = 0; $product_sales = []; fgetcsv($file); // Skip header while (($line = fgetcsv($file)) !== false) { $product_id = $line[1]; $quantity = (int)$line[2]; $price = (float)$line[3]; $total = $quantity * $price; $total_sales += $total; if (!isset($product_sales[$product_id])) { $product_sales[$product_id] = 0; } $product_sales[$product_id] += $total; } fclose($file); arsort($product_sales); $top_product = array_key_first($product_sales); $end_time = microtime(true); $execution_time = ($end_time - $start_time); echo "PHP Execution time: ".$execution_time." seconds\n"; echo "Total Sales: $".$total_sales."\n"; echo "Top Product: ".$top_product." with sales $".$product_sales[$top_product]."\n";
import csv import time # Input file name config input_file = '../generate-csv/sales_data.csv' def parse_csv(file_path): start_time = time.time() total_sales = 0 product_sales = {} with open(file_path, mode='r') as file: reader = csv.DictReader(file) for row in reader: product_id = row['product_id'] quantity = int(row['quantity']) price = float(row['price']) total = quantity * price total_sales += total if product_id not in product_sales: product_sales[product_id] = 0 product_sales[product_id] += total top_product = max(product_sales, key=product_sales.get) execution_time = time.time() - start_time return { 'total_sales': total_sales, 'top_product': top_product, 'top_product_sales': product_sales[top_product], 'execution_time': execution_time, } if __name__ == "__main__": result = parse_csv(input_file) print(f"Python Execution time: {result['execution_time']:.2f} seconds") print(f"Total Sales: ${result['total_sales']:.2f}") print(f"Top Product: {result['top_product']} with sales ${ result['top_product_sales']:.2f}")
Hier sind die Ergebnisse unserer Benchmark-Tests:
Mein Benchmark bringt einige interessante Erkenntnisse zu Tage:
Ausführungszeit: Golang schnitt hinsichtlich der Ausführungszeit am besten ab, dicht gefolgt von PHP8, während NestJS die längste Zeit für die Erledigung der Aufgabe benötigte.
Speichernutzung: Build NestJS zeigte eine effiziente Speichernutzung, während Python einen höheren Speicherverbrauch zeigte.
Einfache Implementierung: Golang bot die einfachste Implementierung, während NestJS mehr Codezeilen und Komplexität erforderte.
Meinen Erkenntnissen zufolge bietet Golang die beste Leistungsgeschwindigkeit und Speichereffizienz, was es zu einer hervorragenden Wahl für die Verarbeitung großer Datenmengen macht.
Den vollständigen Code finden Sie im My Github-Repository
csv-parsing-battle.
Das obige ist der detaillierte Inhalt vonBenchmarking der CSV-Dateiverarbeitung: Golang vs. NestJS vs. PHP vs. Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!