Maison  >  Article  >  développement back-end  >  Analyse comparative du traitement des fichiers CSV : Golang vs NestJS vs PHP vs Python

Analyse comparative du traitement des fichiers CSV : Golang vs NestJS vs PHP vs Python

WBOY
WBOYoriginal
2024-08-12 22:34:021009parcourir

Introduction

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.

Environnement de test

Matériel : MacBook Pro M1, SSD de 256 Go, 8 Go de RAM

Logiciel :

  • macOS Sonoma 14.5
  • PHP 8.3.6
  • Golang 1.22.4
  • Node.js 22.0.0 avec NestJS
  • Python 3.12.3

Données de test

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.

Description de la tâche

Pour chaque langue, le script effectue les tâches suivantes :

  1. Lit le fichier CSV.
  2. Calcule le montant total des ventes.
  3. Identifie le produit avec les ventes les plus élevées.

Mise en œuvre

Voici les scripts utilisés pour chaque langue :

Script Golang :

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)
}

Script NestJS :

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();
  }
}

Script PHP

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";

Script Python

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}")

Résultats

Voici les résultats de nos tests benchmark :

Golang

  • Temps d'exécution : 466,69975ms
  • Ventes totales : 274654985,36 $
  • Meilleur produit : produit 1126 avec des ventes de 305922,81 $

Benchmarking CSV File Processing: Golang vs NestJS vs PHP vs Python

NestJS

  • Temps d'exécution : 6,730134208 secondes
  • Ventes totales : 274654985,36000216 $
  • Meilleur produit : 1126 avec des ventes de 305922,8099999997 $

Benchmarking CSV File Processing: Golang vs NestJS vs PHP vs Python

PHP

  • Temps d'exécution : 1,5142710208893 secondes
  • Ventes totales : 274654985,36 $
  • Meilleur produit : 1126 avec des ventes de 305922,81 $

Benchmarking CSV File Processing: Golang vs NestJS vs PHP vs Python

Python

  • Temps d'exécution : 2,56 secondes
  • Ventes totales : 274654985,36 $
  • Meilleur produit : 1126 avec des ventes de 305922,81 $

Benchmarking CSV File Processing: Golang vs NestJS vs PHP vs Python

Analyse

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é.

Conclusion

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.

Code complet

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn