Skip to content

Commit d951b37

Browse files
committed
rewrite readme.md
1 parent 880f795 commit d951b37

12 files changed

Lines changed: 1394 additions & 706 deletions

.npmignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.DS_Store
2+
Thumbs.db
3+
node_modules/
4+
*.swp
5+
*.swo
6+
7+
# intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
8+
.grunt
9+
10+
pids
11+
logs
12+
results
13+
build
14+
graph.png
15+
.project
16+
.settings
17+
.vscode
18+
docs
19+
devops

bin/options.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"commands": {
33
"parse": "(Default)Parse a csv file to json",
4-
"startserver": "(Deprecated)Start a web server",
54
"version": "Show version of current csvtojson"
65
},
76
"options": {

docs/performance.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Performance Optimisation
2+
3+
Version 1.1.0 is much faster than versions before.
4+
5+
Below test is parsing a 300K records csv
6+
7+
Time | workNum = 1 | workNum = 2 (fork)* | workNum = 3 | workNum = 4
8+
--- | --- | --- | --- | ---
9+
**1.0.3** | 11.806s | 15.945s | 8.611s | 8.314s
10+
**1.1.0** | 9.707s | 10.065s | 5.955s | 4.563s
11+
12+
*when workNum=2, it only creates 1 extra worker to unblock main process. It is reasonalbe it is slightly slower than workerNum=1 (just use main process).
13+
14+
The result shows V1.1.0 has about 30% - 50% performance boost.
15+
16+
# CPU usage leverage
17+
18+
Below is CPU core usages for v1.1.0 when running the test:
19+
20+
Core | workNum = 1 | workNum = 2| workNum = 3 | workNum = 4
21+
--- | --- | --- | --- | ---
22+
Core 1 (Main) | 100% | 25% | 60% | 90%
23+
Core 2 | N/A | 80% | 70% | 70%
24+
Core 3 | N/A | N/A | 70% | 70%
25+
Core 4 | N/A | N/A | N/A | 70%
26+

libs/core/Converter.js

Lines changed: 77 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -39,28 +39,41 @@ function Converter(params,options) {
3939
this._needJson=null;
4040
this._needEmitResult=null;
4141
this._needEmitFinalResult=null;
42+
this._needEmitJson=null;
4243
this._needPush=null;
44+
this._needEmitCsv=null;
45+
this._csvTransf=null;
4346
this.finalResult=[];
4447
// this.on("data", function() {});
4548
this.on("error", function() {});
4649
this.initWorker();
50+
process.nextTick(function(){
51+
if (this._needEmitFinalResult === null){
52+
this._needEmitFinalResult=this.listeners("end_parsed").length > 0
53+
}
54+
if (this._needEmitResult===null){
55+
this._needEmitResult=this.listeners("record_parsed").length>0
56+
}
57+
if (this._needEmitJson === null){
58+
this._needEmitJson=this.listeners("json").length>0
59+
}
60+
if (this._needEmitCsv === null){
61+
this._needEmitCsv=this.listeners("csv").length>0
62+
}
63+
if (this._needJson === null){
64+
this._needJson=this._needEmitJson || this._needEmitFinalResult || this._needEmitResult || this.transform || this._options.objectMode;
65+
}
66+
if (this._needPush === null){
67+
this._needPush = this.listeners("data").length > 0 || this.listeners("readable").length>0
68+
// this._needPush=false;
69+
}
70+
this.param._needParseJson=this._needJson || this._needPush;
71+
72+
}.bind(this))
4773
return this;
4874
}
4975
util.inherits(Converter, Transform);
5076
Converter.prototype._transform = function(data, encoding, cb) {
51-
if (this._needEmitFinalResult === null){
52-
this._needEmitFinalResult=this.listeners("end_parsed").length > 0
53-
}
54-
if (this._needEmitResult===null){
55-
this._needEmitResult=this.listeners("record_parsed").length>0
56-
}
57-
if (this._needJson === null){
58-
this._needJson=this._needEmitFinalResult || this._needEmitResult || this.transform || this._options.objectMode;
59-
}
60-
if (this._needPush === null){
61-
this._needPush = this.listeners("data").length > 0 || this.listeners("readable").length>0
62-
// this._needPush=false;
63-
}
6477
if (this.param.toArrayString && this.started === false) {
6578
this.started = true;
6679
if (this._needPush){
@@ -206,11 +219,21 @@ Converter.prototype.emitResult=function(r){
206219
row=JSON.parse(row)
207220
}
208221
}
209-
if (this.param.constructResult && this._needEmitFinalResult){
210-
this.finalResult.push(resultJson)
211-
}
212222
if (this.transform && typeof this.transform==="function"){
213223
this.transform(resultJson,row,index);
224+
resultStr=null;
225+
}
226+
if (this._needEmitJson){
227+
this.emit("json",resultJson,index)
228+
}
229+
if (this._needEmitCsv){
230+
if (typeof row ==="string"){
231+
row=JSON.parse(row)
232+
}
233+
this.emit("csv",row,index)
234+
}
235+
if (this.param.constructResult && this._needEmitFinalResult){
236+
this.finalResult.push(resultJson)
214237
}
215238
if (this._needEmitResult){
216239
this.emit("record_parsed", resultJson, row, index);
@@ -305,51 +328,65 @@ Converter.prototype.getEol = function(data) {
305328
};
306329
Converter.prototype.fromFile = function(filePath, cb) {
307330
var fs = require('fs');
331+
var rs=null;
332+
this.wrapCallback(cb, function() {
333+
if (rs && rs.destroy){
334+
rs.destroy();
335+
}
336+
});
308337
fs.exists(filePath, function(exist) {
309338
if (exist) {
310-
var rs = fs.createReadStream(filePath);
339+
rs = fs.createReadStream(filePath);
311340
rs.pipe(this);
312-
this.wrapCallback(cb, function() {
313-
rs.destroy();
314-
});
315341
} else {
316-
cb(new Error(filePath + " cannot be found."));
342+
this.emit('error',new Error("File not exist"))
317343
}
318344
}.bind(this));
319345
return this;
320346
}
347+
Converter.prototype.fromStream=function(readStream,cb){
348+
if (cb && typeof cb ==="function"){
349+
this.wrapCallback(cb);
350+
}
351+
process.nextTick(function(){
352+
readStream.pipe(this);
353+
}.bind(this))
354+
return this;
355+
}
356+
Converter.prototype.transf=function(func){
357+
this.transform=func;
358+
return this;
359+
}
321360
Converter.prototype.fromString = function(csvString, cb) {
322-
var rs = new Readable();
323-
var offset = 0;
324361
if (typeof csvString != "string") {
325362
return cb(new Error("Passed CSV Data is not a string."));
326363
}
327-
rs._read = function(len) {
328-
// console.log(offset,len,csvString.length);
329-
var sub = csvString.substr(offset, len);
330-
this.push(sub);
331-
offset += len;
332-
if (offset >= csvString.length) {
333-
this.push(null);
334-
}
335-
};
336-
rs.pipe(this);
337364
if (cb && typeof cb === "function") {
338365
this.wrapCallback(cb, function() {
339-
rs.pause();
340366
});
341367
}
368+
process.nextTick(function(){
369+
this.end(csvString)
370+
}.bind(this))
342371
return this;
343372
};
344373
Converter.prototype.wrapCallback = function(cb, clean) {
345-
this.once("end_parsed", function(res) {
346-
if (!this.hasError) {
347-
cb(null, res);
348-
}
349-
}.bind(this));
374+
375+
if (clean === undefined){
376+
clean=function(){}
377+
}
378+
if (cb && typeof cb ==="function"){
379+
this.once("end_parsed", function(res) {
380+
if (!this.hasError) {
381+
cb(null, res);
382+
}
383+
}.bind(this));
384+
}
350385
this.once("error", function(err) {
351386
this.hasError=true;
352-
cb(err);
387+
if (cb && typeof cb ==="function"){
388+
cb(err);
389+
}
353390
clean();
354391
}.bind(this));
355392
}

libs/core/defParam.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ module.exports=function(params){
1616
checkColumn: false, //whether check column number of a row is the same as headers. If column number mismatched headers number, an error of "mismatched_column" will be emitted.. default: false
1717
escape:'"' //escape char for quoted column
1818
};
19+
if (!params){
20+
params={};
21+
}
1922
for (var key in params) {
2023
if (params.hasOwnProperty(key)) {
2124
_param[key] = params[key];

libs/core/linesToJson.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,31 @@ var CSVError=require("./CSVError");
99
* @return {[type]} [{err:null,json:obj,index:line,row:[csv row]}]
1010
*/
1111
module.exports=function(lines,params,idx){
12-
if (!params._headers){
13-
params._headers=[];
12+
if (params._needParseJson){
13+
if (!params._headers){
14+
params._headers=[];
15+
}
16+
if (!params.parseRules){
17+
var row=params._headers;
18+
params.parseRules=parserMgr.initParsers(row,params);
19+
}
20+
return processRows(lines,params,idx);
21+
}else{
22+
return justReturnRows(lines,params,idx);
1423
}
15-
if (!params.parseRules){
16-
var row=params._headers;
17-
params.parseRules=parserMgr.initParsers(row,params);
24+
}
25+
26+
function justReturnRows(lines,params,idx){
27+
var rtn=[];
28+
for (var i=0;i<lines.length;i++){
29+
rtn.push({
30+
err:null,
31+
json:{},
32+
index:idx++,
33+
row:lines[i]
34+
})
1835
}
19-
return processRows(lines,params,idx);
36+
return rtn;
2037
}
2138
function processRows(csvRows, params,startIndex) {
2239
var count = csvRows.length;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"email": "t3dodson@gmail.com"
1919
}
2020
],
21-
"version": "1.0.3",
21+
"version": "1.1.0",
2222
"keywords": [
2323
"csv",
2424
"csvtojson",

0 commit comments

Comments
 (0)