各种读取csv文件的工具性能比较

在翻阅calamine作者的quick-csv存储库时无意中看到有个10年前的csv读取比赛, 把比赛选手源程序下载下来测试看到底有多快。

git clone https://bitbucket.org/ewanhiggs/csv-game.git

这些源程序只有比赛程序本身,依赖的文件有的在主页,有的在makefile中写出。冠军是一个叫csvmonkey的程序,如下所示

#include <iostream>
#include <iterator>#include "csvmonkey.hpp"
using namespace csvmonkey;int main(int argc, char* argv[])
{if(argc < 2) {return 1;}MappedFileCursor cursor;if(! cursor.open(argv[1])) {// new behaviour for csvmonkey returns 0 for empty files.std::cout << 0 << std::endl;return 0;}CsvReader reader(cursor);CsvCursor &row = reader.row();int sum = 0;while(reader.read_row()) {sum += row.count;}std::cout << sum << std::endl;
}

它的主要实现都在头文件csvmonkey.hpp里,找来编译执行了,结果不太快,500万行的读取正确,用时23秒,100万行41列的读取失败,没有文档,不知怎么改。

wget https://raw.githubusercontent.com/dw/csvmonkey/csv-game/csvmonkey.hppg++ csv.cc -w -pedantic -std=c++11 -g -O3 -fpic -msse4.2 -march=native -DNDEBUG -o csvmonkey -I .root@6ae32a5ffcde:/par# time ./csvmonkey "5m Sales Records.csv"
70000000real    0m23.437s
user    0m0.388s
sys     0m1.325s
root@6ae32a5ffcde:/par# time ./csvmonkey "NYC_311_SR_2010-2020-sample-1M.csv"
1060693607
Segmentation fault (core dumped)real    0m19.954s
user    0m0.194s
sys     0m1.147s

再拿基于libcsv的程序来测,它在列表中是第8名

#include <csv.h>
#include <stdio.h>
#include <string.h>void field_count(void* str, size_t str_len, void* data) {int* count = (int*)data;*count += 1;
}const int READ_SZ = 1024 * 1024;int main (int argc, char* argv[]) {struct csv_parser parser = {0};csv_init(&parser, CSV_APPEND_NULL);FILE* f = fopen(argv[1], "r");char *buf = (char*)malloc(READ_SZ);size_t buflen = READ_SZ;int count = 0; while((buflen = fread(buf, 1, READ_SZ, f))  > 0){csv_parse(&parser, buf, buflen, field_count, 0, &count);}printf("%d\n", count);fclose(f);free(buf);csv_free(&parser);return EXIT_SUCCESS;
}

效果好了很多,都在3秒左右,但读出的列数有点差距,应该是标题行影响,但第一个难以理解,14列怎么读成13列了。

gcc csv.c libcsv.c -Werror -Wall -pedantic -std=c11 -g -O3 -fpic -march=native -o libcsv -I .
root@6ae32a5ffcde:/par# time ./libcsv "5m Sales Records.csv"
70000013real    0m3.608s
user    0m1.301s
sys     0m0.100s
root@6ae32a5ffcde:/par# time ./libcsv "NYC_311_SR_2010-2020-sample-1M.csv"
41000041real    0m3.078s
user    0m1.083s
sys     0m0.109s

再拿我常用的Duckdb来读,效率高了很多。读取统计行数都在2秒左右,写入内存表也不过增加了0.2秒。对读入的数据进行总结,内容也都正确。

D .timer on
D SET enable_progress_bar =false;D select count(*) from '5m Sales Records.csv';
┌────────────────┐
│  count_star()  │
│     int64      │
├────────────────┤
│    5000000     │
│ (5.00 million) │
└────────────────┘
Run Time (s): real 2.329 user 0.998917 sys 0.234929
D select count(*) from 'NYC_311_SR_2010-2020-sample-1M.csv';
┌────────────────┐
│  count_star()  │
│     int64      │
├────────────────┤
│    1000000     │
│ (1.00 million) │
└────────────────┘
Run Time (s): real 1.981 user 0.649826 sys 0.196659
D create table t as from '5m Sales Records.csv';
Run Time (s): real 2.585 user 3.853148 sys 0.752251
D summarize t;
┌────────────────┬─────────────┬─────────────┬────────────────────┬───┬────────────────────┬─────────┬─────────────────┐
│  column_name   │ column_type │     min     │        max         │ … │        q75         │  count  │ null_percentage │
│    varcharvarcharvarcharvarchar       │   │      varchar       │  int64  │  decimal(9,2)   │
├────────────────┼─────────────┼─────────────┼────────────────────┼───┼────────────────────┼─────────┼─────────────────┤
│ Region         │ VARCHAR     │ Asia        │ Sub-Saharan Africa │ … │ NULL50000000.00 │
│ Country        │ VARCHAR     │ Afghanistan │ Zimbabwe           │ … │ NULL50000000.00 │
│ Item TypeVARCHAR     │ Baby Food   │ Vegetables         │ … │ NULL50000000.00 │
│ Sales Channel  │ VARCHAR     │ Offline     │ Online             │ … │ NULL50000000.00 │
│ Order Priority │ VARCHAR     │ C           │ M                  │ … │ NULL50000000.00 │
│ Order DateDATE2010-01-012020-09-10         │ … │ 2018-01-0850000000.00 │
│ Order ID       │ BIGINT100000321999999892          │ … │ 77539938850000000.00 │
│ Ship DateDATE2010-01-012020-10-30         │ … │ 2018-02-0150000000.00 │
│ Units Sold     │ BIGINT110000              │ … │ 749850000000.00 │
│ Unit Price     │ DOUBLE9.33668.27             │ … │ 428.793747566488850000000.00 │
│ Unit Cost      │ DOUBLE6.92524.96             │ … │ 307.0304857341750000000.00 │
│ Total Revenue  │ DOUBLE9.336682700.0          │ … │ 1823813.983183333750000000.00 │
│ Total Cost     │ DOUBLE6.925249600.0          │ … │ 1203364.150452026950000000.00 │
│ Total Profit   │ DOUBLE2.411738700.0          │ … │ 566819.027875001550000000.00 │
├────────────────┴─────────────┴─────────────┴────────────────────┴───┴────────────────────┴─────────┴─────────────────┤
│ 14 rows                                                                                         12 columns (7 shown) │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 0.792 user 10.106701 sys 0.037936
D create table t2 as from 'NYC_311_SR_2010-2020-sample-1M.csv';
Run Time (s): real 2.285 user 2.901837 sys 0.686295
D summarize t2;
┌──────────────────────┬─────────────┬──────────────────────┬───┬──────────────────────┬─────────┬─────────────────┐
│     column_name      │ column_type │         min          │ … │         q75          │  count  │ null_percentage │
│       varcharvarcharvarchar        │   │       varchar        │  int64  │  decimal(9,2)   │
├──────────────────────┼─────────────┼──────────────────────┼───┼──────────────────────┼─────────┼─────────────────┤
│ Unique KeyBIGINT11465364             │ … │ 4020821610000000.00 │
│ Created DateTIMESTAMP2010-01-01 00:00:00  │ … │ 2018-07-30 12:48:4…  │ 10000000.00 │
│ Closed DateTIMESTAMP1900-01-01 00:00:00  │ … │ 2018-08-04 11:42:5…  │ 10000002.86 │
│ Agency               │ VARCHAR3-1-1                │ … │ NULL10000000.00 │
│ Agency Name          │ VARCHAR3-1-1                │ … │ NULL10000000.00 │
│ Complaint TypeVARCHAR../../WEB-INF/web.…  │ … │ NULL10000000.00 │
│ Descriptor           │ VARCHAR1 Missed Collection  │ … │ NULL10000000.30 │
│ Location TypeVARCHAR1-, 2- and 3- Fami…  │ … │ NULL100000023.91 │
│ Incident Zip         │ VARCHAR*                    │ … │ NULL10000005.50 │
│ Incident Address     │ VARCHAR* *                  │ … │ NULL100000017.47 │
│ Street Name          │ VARCHAR*                    │ … │ NULL100000017.47 │
│ Cross Street 1VARCHAR1 AVE                │ … │ NULL100000032.04 │
│ Cross Street 2VARCHAR1 AVE                │ … │ NULL100000032.36 │
│ Intersection Stree…  │ VARCHAR1 AVE                │ … │ NULL100000076.74 │
│ Intersection Stree…  │ VARCHAR1 AVE                │ … │ NULL100000076.77 │
│ Address TypeVARCHAR     │ ADDRESS              │ … │ NULL100000012.58 │
│ City                 │ VARCHAR*                    │ … │ NULL10000006.20 │
│ Landmark             │ VARCHAR1 AVENUE             │ … │ NULL100000091.28 │
│ Facility TypeVARCHAR     │ DSNY Garage          │ … │ NULL100000014.55 │
│ StatusVARCHAR     │ Assigned             │ … │ NULL10000000.00 │
│ Due DateTIMESTAMP1900-01-02 00:00:00  │ … │ 2017-09-22 19:44:2…  │ 100000064.78 │
│ Resolution Descrip…  │ VARCHAR     │ A DOB violation wa…  │ … │ NULL10000002.05 │
│ Resolution Action …  │ TIMESTAMP2009-12-31 01:35:00  │ … │ 2018-08-10 13:25:1…  │ 10000001.51 │
│ Community Board      │ VARCHAR0 Unspecified        │ … │ NULL10000000.00 │
│ BBL                  │ VARCHAR0000000000           │ … │ NULL100000024.30 │
│ Borough              │ VARCHAR     │ BRONX                │ … │ NULL10000000.00 │
│ X Coordinate (Stat…  │ BIGINT913281               │ … │ 101825510000008.53 │
│ Y Coordinate (Stat…  │ BIGINT121152               │ … │ 23490710000008.53 │
│ Open Data Channel …  │ VARCHAR     │ MOBILE               │ … │ NULL10000000.00 │
│ Park Facility Name   │ VARCHAR"Uncle" Vito F. Ma…  │ … │ NULL10000000.00 │
│ Park Borough         │ VARCHAR     │ BRONX                │ … │ NULL10000000.00 │
│ Vehicle TypeVARCHAR     │ Ambulette / Paratr…  │ … │ NULL100000099.97 │
│ Taxi Company Borough │ VARCHAR     │ BRONX                │ … │ NULL100000099.92 │
│ Taxi Pick Up Locat…  │ VARCHAR1 5 AVENUE MANHATTAN │ … │ NULL100000099.21 │
│ Bridge Highway Name  │ VARCHAR145th St. Br - Len…  │ … │ NULL100000099.77 │
│ Bridge Highway Dir…  │ VARCHAR     │ Bronx Bound          │ … │ NULL100000099.77 │
│ Road Ramp            │ VARCHAR     │ N/A                  │ … │ NULL100000099.77 │
│ Bridge Highway Seg…  │ VARCHAR1-1-1265963747       │ … │ NULL100000099.76 │
│ Latitude             │ DOUBLE40.1123853           │ … │ 40.80288457482914100000025.47 │
│ Longitude            │ DOUBLE-77.5195844          │ … │ -73.87602468658496100000025.47 │
│ Location             │ VARCHAR(40.1123853, -77.5…  │ … │ NULL100000025.47 │
├──────────────────────┴─────────────┴──────────────────────┴───┴──────────────────────┴─────────┴─────────────────┤
│ 41 rows                                                                                     12 columns (6 shown) │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 0.332 user 2.741898 sys 0.049018

补记:
我用calamine作者的参赛代码quick-reader编译时报错,将源文件交给张泽鹏先生审查,他说那是古早的格式,现在Cargo.toml要加入edition = “2024”,依赖代码的版本也修改为quick-csv ="0.1.6"就能正常编译了

quick-reader修改前Cargo.toml

[package]name = "quick-reader"
version = "0.0.1"
authors = [ "Johann Tuffe <tafia973@gmail.com>" ][[bin]]
name = "quick-reader"[dependencies]
quick-csv = "0.1"[profile.release]
opt-level = 3
lto = true

quick-reader修改后Cargo.toml

[package]
name = "quick-reader"
version = "0.1.0"
edition = "2024"[dependencies]
quick-csv = "0.1.6"

quick-reader源代码将extern crate quick_csv as csv;改为use quick_csv as csv;同时添加use std;并把::std改为std。
修改前

extern crate quick_csv as csv;fn main() {let fpath = ::std::env::args().nth(1).unwrap();let rdr = csv::Csv::from_file(fpath).unwrap();let sum = rdr.into_iter().map(|r| r.unwrap().len()).fold(0usize, |c, n| c + n);println!("{}", sum);
}

修改后

use quick_csv as csv;
use std;fn main() {let fpath = std::env::args().nth(1).unwrap();let rdr = csv::Csv::from_file(fpath).unwrap();let sum = rdr.into_iter().map(|r| r.unwrap().len()).fold(0usize, |c, n| c + n);println!("{}", sum);
}

编译执行

time /par/quick-reader/target/release/quick-reader /par/NYC_311_SR_2010-2020-sample-1M.csv
41000041real    0m9.702s
user    0m0.449s
sys     0m0.394s
time /par/quick-reader/target/release/quick-reader "/par/5m Sales Records.csv"
70000014real    0m12.335s
user    0m0.636s
sys     0m0.564s

还是不如libcsv快, 但是结果很正确,一个字段都不差。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/93384.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/93384.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML <iframe> 标签 如何把html写入iframe标签

标签 如何把html写入iframe标签 使用srcdoc属性 HTML iframe 标签 参考 定义和用法 <iframe> 标签定义行内框架&#xff08;内联框架&#xff09;。 行内框架用于在当前 HTML 文档中嵌入另一个文档。

Java Spark例子程序

目录spark基础&rdddocsRDDspark架构Spark 对比 hadoop MapReducespark maven依赖Spark的checkpointtransformations、shuffle、actionsreduceByKey的用法groupByKey的用法count / count distinct例子&#xff1a;单词计数例子&#xff1a;一批人员年龄数据求平均(rdd)例子&…

《代码重生:杨蓉与62.webp》

《代码重生&#xff1a;杨蓉与62.webp》2045年&#xff0c;星耀城。雨丝斜织在量子玻璃幕墙上&#xff0c;霓虹倒影如液态代码流淌。杨蓉坐在“时光回溯实验室”的终端前&#xff0c;面前悬浮着一行行泛黄的日志——那是从2018年GitHub快照中提取的原始构建记录。她指尖轻点&am…

软考 系统架构设计师系列知识点之杂项集萃(123)

接前一篇文章:软考 系统架构设计师系列知识点之杂项集萃(122) 第227题 某公司欲开发一种工业机器人,用来进行汽车零件的装配。公司的架构师经过分析与讨论,给出了该机器人控制软件的两种候选架构方案:闭环控制和分层结构。以下对于这两者候选框架的选择路由,错误的是(…

Sonatype Nexus Repository Manager docker版本安装

docker 网址 https://hub.docker.com/r/sonatype/nexus3 拉取镜像 docker pull sonatype/nexus3创建docker docker run -d -p 8081:8081 --name nexus --restart always sonatype/nexus3查看密码 docker exec nexus cat /nexus-data/admin.password导出docker image 镜像 …

Java Stream API:让业务数据处理更优雅

在 Java 业务开发中&#xff0c;我们经常需要对集合数据进行**筛选&#xff08;filter&#xff09;、转换&#xff08;map&#xff09;、聚合&#xff08;collect&#xff09;**等操作。比如从一批结果中过滤出符合条件的记录&#xff0c;就像这样&#xff1a; 假数据&#xf…

Win11和Win10共享打印机提示709用添加Windows凭据来解决的小方法

我们在使用共享打印机打印文件时或者添加共享打印机的时候&#xff0c;遇到了系统提示错误709的问题&#xff0c;导致打印失败、共享失败&#xff0c;如果你现在正好也遇到了这一问题&#xff0c;那么不妨来看看下面吴师傅使用过的这个方法&#xff0c;希望可以能够帮助大家有效…

【嵌入式STM32】I2C总结

I2C诞生于上世纪80年代初&#xff0c;由飞利浦&#xff08;现在的恩智浦NXP&#xff09;为解决微控制器与外围芯片之间繁琐的连接问题而设计。 仅仅两根线——SCL&#xff08;时钟线&#xff09;和SDA&#xff08;数据线&#xff09;&#xff0c;就能实现多设备间的双向通信。 …

WPF 监控CPU、内存性能

本段代码是一个封装的用户控件<UserControl x:Class"YF_Frame.PerformanceMonitor"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc"http://schemas.…

Rust学习笔记(四)|结构体与枚举(面向对象、模式匹配)

本篇文章包含的内容1 结构体1.1 定义和初始化结构体1.2 Tuple Struct1.3 结构体方法&#xff08;Rust 面向对象&#xff09;1.4 关联函数2 枚举2.1 定义和使用枚举2.2 将数据附加到枚举的变体中2.3 Option 枚举2.4 模式匹配2.4.1 match语句2.4.2 if let语句1 结构体 1.1 定义和…

C++——分布式

文章目录一、什么是分布式&#xff1f;核心特点为什么需要分布式&#xff1f;分布式 vs 集中式常见分布式场景挑战与难点二、 简述下CAP理论2.1 简述2.2 详细三、 简述下分布式中的2PC2.1 详细3.2 简述三 、简述下Raft协议3.1 详细3.2 简述四 grpc框架4.1 RPC&#xff08;Remot…

Redis面试精讲 Day 20:Redis大规模部署性能调优

【Redis面试精讲 Day 20】Redis大规模部署性能调优 开篇 欢迎来到"Redis面试精讲"系列第20天&#xff01;今天我们将深入探讨Redis在大规模部署场景下的性能调优策略&#xff0c;这是高级工程师和架构师面试必考的核心知识点。本文将从操作系统配置、Redis参数调优…

[微服务]ELK Stack安装与配置全指南

目录 一、ELK相关介绍 1.1 什么是ELK Stack 1.2 ELK核心组件与功能 1.3 ELK优势 1.4 ES数据库结构对比SqlServer 二、安装ELK 2.1 window安装 2.2 Docker下环境搭建 2.2.1 安装7.16.3版本ElasticSearch 2.2.2 安装7.16.3版本Kibana : 2.2.3 安装8.0.0版本ElasticSea…

java项目怎么实现用户行为分析、漏斗转化、数据可视化报表。

在 Java 项目中实现用户行为分析、漏斗转化和数据可视化报表是一个系统性的工作&#xff0c;需要从数据采集、存储、分析到展示的完整链路设计。以下是一个可行的实现方案&#xff1a;1. 整体架构设计建议采用分层架构&#xff1a;数据采集层&#xff1a;收集用户行为数据数据存…

缓存元数据损坏操作步骤(lvmcache修复)

现象为:机械盘丢失cvol-cmeta卷如图所示,lvm逻辑卷中缺失缓存的lvm,这边以只读cache为例日志现象报错信息为:lvmcache_cvol failed manual repair required!lvmcache_cvol failed: manual repair required! 这类报错&#xff0c;本质上是 LVM cache 池&#xff08;cache-pool&…

使用CMAKE-GUI生成Visual Studio项目

使用CMAKE-GUI生成Visual Studio项目第一种&#xff0c;如果我们想把以Cmake构建的项目移植VS上&#xff0c;就可以使用Cmake来生成.sln文件 准备生成的目录文件先准备好我们要打包的源代码等文件&#xff08;放在resource下&#xff09;使用cmake-gui工具来构建&#xff08;命…

20道DOM相关前端面试题

DOM 相关面试题及答案 什么是 DOM&#xff1f;DOM 树的结构是怎样的&#xff1f; DOM&#xff08;文档对象模型&#xff0c;Document Object Model&#xff09;是 HTML/XML 文档的编程接口&#xff0c;将文档结构化为树形节点集合&#xff0c;允许程序动态访问和修改文档内容、…

CVE-2021-4300漏洞复现

Adminer是一个PHP编写的开源数据库管理工具&#xff0c;支持MySQL、MariaDB、PostgreSQL、SQLite、MS SQL、Oracle、Elasticsearch、MongoDB等数据库。在其版本1.12.0到4.6.2之间存在一处因为MySQL LOAD DATA LOCAL导致的文件读取漏洞。 一、伪造服务器 利用mysql-fake-serve…

【LeetCode题解】LeetCode 35. 搜索插入位置

【题目链接】 35. 搜索插入位置 【题目描述】 【题解】 通过题目可以知道这是一道经典的二分查找的题目&#xff0c;对于二分查找的题目&#xff0c;根据需要查找的两个边界点&#xff0c;分为两个不同的模板&#xff0c;如下图所示。 这道题要求在数组中查找目标值并返回其索…

RK3568 NPU RKNN(五):RKNN-ToolKit-lite2板端推理

文章目录1、前言2、目标3、安装RKNN-ToolKit-lite23.1、安装环境3.2、安装RKNN-ToolKit-lite23.3、验证4、完整的测试程序5、运行测试程序6、程序拆解7、总结1、前言 本文仅记录本人学习过程&#xff0c;不具备教学指导意义。 2、目标 之前提到过&#xff0c;RKNN-Toolkit2-…