Le traitement efficace de gros fichiers CSV est une exigence courante dans de nombreuses applications, de l'analyse de données aux processus ETL (Extract, Transform, Load). Dans cet article, je souhaite évaluer les performances de quatre langages de programmation populaires (Golang, NodeJS avec NestJS, PHP et Python) dans la gestion de fichiers CSV volumineux sur un MacBook Pro M1. Mon objectif est de déterminer quelle langue offre les meilleures performances pour cette tâche.
Matériel : MacBook Pro M1, SSD de 256 Go, 8 Go de RAM
Logiciel :
J'ai utilisé un fichier CSV synthétique nommé sales_data.csv avec environ 1 million de lignes, chacune contenant des détails de transaction tels que transaction_id, product_id, quantité, prix et horodatage.
Pour chaque langue, le script effectue les tâches suivantes :
Voici les scripts utilisés pour chaque langue :
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(); } }
ventes.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}")
Voici les résultats de nos tests benchmark :
Mon benchmark révèle plusieurs informations intéressantes :
Temps d'exécution : Golang a obtenu les meilleurs résultats en termes de temps d'exécution, suivi de près par PHP8, tandis que NestJS a mis le plus de temps pour terminer la tâche.
Utilisation de la mémoire : Build NestJS a démontré une utilisation efficace de la mémoire, tandis que Python a montré une consommation de mémoire plus élevée.
Facilité de mise en œuvre : Golang a fourni l'implémentation la plus simple, tandis que NestJS nécessitait plus de lignes de code et de complexité.
D'après mes découvertes, Golang offre la meilleure vitesse de performances et la meilleure efficacité de mémoire, ce qui en fait un excellent choix pour gérer de grands ensembles de données.
Vous pouvez obtenir le code complet sur le référentiel My Github
bataille d'analyse csv.
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!