├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── README.md ├── othersolution.js ├── package-lock.json ├── package.json ├── readFile.js ├── readFileEventStream.js ├── readFileStream.js └── test.txt /.gitignore: -------------------------------------------------------------------------------- 1 | itcont.txt 2 | node_modules/ -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${workspaceFolder}/readFileStream.js" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node.js Large File / Data Reading & Performance Testing 2 | 3 | This is an example of 3 different ways to use Node.js to process big data files. One file is the Node.js' `fs.readFile()`, another is with Node.js' `fs.createReadSteam()`, and the final is with the help of the NPM module `EventStream`. 4 | 5 | There is also use of `console.time` and `console.timeEnd` to determine the performance of the 3 different implementations, and which is most efficient processing the files. 6 | 7 | ### To Download the Really Large File 8 | Download the large file zip here: https://www.fec.gov/files/bulk-downloads/2018/indiv18.zip 9 | 10 | The main file in the zip: `itcont.txt`, can only be processed by the `readFileEventStream.js` file, the other two implementations can't handle the 2.55GB file size in memory (Node.js can only hold about 1.5GB in memory at one time).* 11 | 12 | *Caveat: You can override the standard Node memory limit using the CLI arugment `max-old-space-size=XYZ`. To run, pass in `node --max-old-space-size=8192 .js` (this will increase Node's memory limit to 8gb - just be careful not to make it too large that Node kills off other processes or crashes because its run out of memory) 13 | 14 | ### To Run 15 | Before the first run, run `npm install` from the command line to install the `event-stream` and `performance.now` packages from Node. 16 | 17 | Add the file path for one of the files (could be the big one `itcont.txt` or any of its smaller siblings in the `indiv18` folder that were just downloaded), and type the command `node ` in the command line. 18 | 19 | Then you'll see the answers required from the file printed out to the terminal. 20 | 21 | ### To Check Performance Testing 22 | Use one of the smaller files contained within the `indiv18` folder - they're all about 400MB and can be used with all 3 implementations. Run those along with the `console.time` and `performance.now()` references and you can see which solution is more performant and by how much. 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /othersolution.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const readline = require('readline'); 5 | const { performance: perf } = require('perf_hooks'); 6 | 7 | /** 8 | * Finds the largest value of all fields in `obj` 9 | * and returns its field name (key). 10 | */ 11 | function maxEntry(obj) { 12 | let maxValue = 0; 13 | let maxKey = null; 14 | for (let key of Object.keys(obj)) { 15 | if (obj[key] > maxValue) { 16 | maxKey = key; 17 | maxValue = obj[key]; 18 | } 19 | } 20 | return maxKey; 21 | } 22 | 23 | function getFirstName(name) { 24 | // this code copied verbatim from [Paige Niedringhaus](https://github.com/paigen11/file-read-challenge/blob/master/readFileStream.js) 25 | let firstHalfOfName = name.split(', ')[1]; 26 | if (firstHalfOfName !== undefined) { 27 | firstHalfOfName.trim(); 28 | // filter out middle initials 29 | if (firstHalfOfName.includes(' ') && firstHalfOfName !== ' ') { 30 | let firstName = firstHalfOfName.split(' ')[0]; 31 | return firstName.trim(); 32 | } else { 33 | return firstHalfOfName; 34 | } 35 | } 36 | } 37 | 38 | function getFirstNameRegEx(name) { 39 | // idea for this taken from [Stuart Marks](https://stuartmarks.wordpress.com/2019/01/11/processing-large-files-in-java/) 40 | // the documentation assures me that a regex in this form is compiled at parse-time 41 | // and is indeed a constant in memory. 42 | const regex = /, (\S+)/; 43 | const match = regex.exec(name); 44 | return match && match[1]; 45 | } 46 | 47 | const numberFormat4 = new Intl.NumberFormat('en-us', { 48 | maximumSignificantDigits: 4, 49 | }); 50 | const numberFormatFull = new Intl.NumberFormat('en-us'); 51 | 52 | function main(args) { 53 | console.log(`Opening file '${args[0]}'.`); 54 | const rl = readline.createInterface({ 55 | input: fs.createReadStream(args[0]), 56 | crlfDelay: Infinity, 57 | }); 58 | 59 | const timeStartReadLoop = perf.now(); 60 | let timeInsideReadLoop = 0; 61 | 62 | const nameCounts = {}; 63 | let lineCount = 0; 64 | rl.on('line', line => { 65 | const timeStartInside = perf.now(); 66 | lineCount++; 67 | const fields = line.split('|'); 68 | const date = fields[4]; 69 | const name = getFirstNameRegEx(fields[7]); // to count full names, just use `fields[7];` 70 | nameCounts[name] = (nameCounts[name] || 0) + 1; 71 | console.log(nameCounts); 72 | timeInsideReadLoop += perf.now() - timeStartInside; 73 | }); 74 | 75 | rl.on('close', function() { 76 | const totalTime = numberFormat4.format(perf.now() - timeStartReadLoop); 77 | const insideTime = numberFormat4.format(timeInsideReadLoop); 78 | console.log(`Total time for reading and processing file: ${totalTime}ms.`); 79 | console.log( 80 | `Thereof time spent in custom processing code: ${insideTime}ms.`, 81 | ); 82 | 83 | console.log(`Dataset has ${numberFormatFull.format(lineCount)} entries.`); 84 | 85 | const numUniqueNames = numberFormatFull.format( 86 | Object.keys(nameCounts).length, 87 | ); 88 | console.log(`${numUniqueNames} different names found in file.`); 89 | 90 | const name = maxEntry(nameCounts); 91 | const nameOccurrences = numberFormatFull.format(nameCounts[name]); 92 | console.log( 93 | `The most common name is '${name}' with ${nameOccurrences} occurrences.`, 94 | ); 95 | }); 96 | 97 | console.log(`Getting started...`); 98 | } 99 | 100 | // note that in older versions of node, you need to `.splice(process.execArgv.length + 2)` 101 | // but my v10.15 seems to already remove the runtime's arguments from the program's. 102 | main(process.argv.splice(2)); 103 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "readfilechallenge", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "duplexer": { 8 | "version": "0.1.1", 9 | "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", 10 | "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" 11 | }, 12 | "event-stream": { 13 | "version": "3.3.4", 14 | "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", 15 | "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", 16 | "requires": { 17 | "duplexer": "~0.1.1", 18 | "from": "~0", 19 | "map-stream": "~0.1.0", 20 | "pause-stream": "0.0.11", 21 | "split": "0.3", 22 | "stream-combiner": "~0.0.4", 23 | "through": "~2.3.1" 24 | } 25 | }, 26 | "from": { 27 | "version": "0.1.7", 28 | "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", 29 | "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" 30 | }, 31 | "map-stream": { 32 | "version": "0.1.0", 33 | "resolved": "http://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", 34 | "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" 35 | }, 36 | "pause-stream": { 37 | "version": "0.0.11", 38 | "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", 39 | "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", 40 | "requires": { 41 | "through": "~2.3" 42 | } 43 | }, 44 | "performance-now": { 45 | "version": "2.1.0", 46 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 47 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 48 | }, 49 | "split": { 50 | "version": "0.3.3", 51 | "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", 52 | "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", 53 | "requires": { 54 | "through": "2" 55 | } 56 | }, 57 | "stream-combiner": { 58 | "version": "0.0.4", 59 | "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", 60 | "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", 61 | "requires": { 62 | "duplexer": "~0.1.1" 63 | } 64 | }, 65 | "through": { 66 | "version": "2.3.8", 67 | "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", 68 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "readfilechallenge", 3 | "version": "1.0.0", 4 | "description": "This is an example of 3 different ways to use Node.js to process big data files. One file is the Node.js' `fs.readFile()`, another is with Node.js' `fs.createReadSteam()`, and the final is with the help of the NPM module `EventStream`.", 5 | "main": "readFile.js", 6 | "dependencies": { 7 | "event-stream": "4.0.1", 8 | "performance-now": "^2.1.0" 9 | }, 10 | "devDependencies": {}, 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/paigen11/file-read-challenge.git" 17 | }, 18 | "author": "Paige Niedringhaus", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/paigen11/file-read-challenge/issues" 22 | }, 23 | "homepage": "https://github.com/paigen11/file-read-challenge#readme" 24 | } 25 | -------------------------------------------------------------------------------- /readFile.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var now = require('performance-now'); 3 | 4 | var totalLines = 0; 5 | var lines = []; 6 | var names = []; 7 | var firstNames = []; 8 | var dupeNames = {}; 9 | var dateDonationCount = []; 10 | var dateDonations = {}; 11 | 12 | fs.readFile('itcont.txt', 'utf8', (err, contents) => { 13 | console.time('line count'); 14 | let t0 = now(); 15 | if (contents !== undefined) { 16 | totalLines = contents.split('\n').length - 1; 17 | } 18 | console.log(totalLines); 19 | let t1 = now(); 20 | console.timeEnd('line count'); 21 | console.log( 22 | `Performance now line count timing: ` + (t1 - t0).toFixed(3) + `ms`, 23 | ); 24 | 25 | console.time('names'); 26 | t0 = now(); 27 | if (contents !== undefined) { 28 | lines = contents.split('\n'); 29 | lines.forEach(line => { 30 | var name = line.split('|')[7]; 31 | names.push(name); 32 | }); 33 | } 34 | 35 | console.log(names[432]); 36 | console.log(names[43243]); 37 | t1 = now(); 38 | console.timeEnd('names'); 39 | console.log(`Performance now names timing: ` + (t1 - t0).toFixed(3) + `ms`); 40 | 41 | console.time('most common first name'); 42 | t0 = now(); 43 | names.forEach(name => { 44 | var firstHalfOfName = name.split(', ')[1]; 45 | if (firstHalfOfName !== undefined) { 46 | firstHalfOfName.trim(); 47 | 48 | if (firstHalfOfName !== ' ' && firstHalfOfName.includes(' ')) { 49 | firstName = firstHalfOfName.split(' ')[0]; 50 | firstName.trim(); 51 | firstNames.push(firstName); 52 | } else { 53 | firstNames.push(firstHalfOfName); 54 | } 55 | } 56 | }); 57 | 58 | firstNames.forEach(x => { 59 | dupeNames[x] = (dupeNames[x] || 0) + 1; 60 | }); 61 | var sortedDupeNames = []; 62 | sortedDupeNames = Object.entries(dupeNames); 63 | 64 | sortedDupeNames.sort((a, b) => { 65 | return b[1] - a[1]; 66 | }); 67 | console.log(sortedDupeNames[0]); 68 | t1 = now(); 69 | console.timeEnd('most common first name'); 70 | console.log( 71 | `Performance now first name timing: ` + (t1 - t0).toFixed(3) + `ms`, 72 | ); 73 | 74 | console.time('total donations for each month'); 75 | t0 = now(); 76 | lines.forEach(line => { 77 | var timestamp = line.split('|')[4].slice(0, 6); 78 | var formattedTimestamp = 79 | timestamp.slice(0, 4) + '-' + timestamp.slice(4, 6); 80 | dateDonationCount.push(formattedTimestamp); 81 | }); 82 | 83 | dateDonationCount.forEach(x => { 84 | dateDonations[x] = (dateDonations[x] || 0) + 1; 85 | }); 86 | logDateElements = (key, value, map) => { 87 | console.log( 88 | `Donations per month and year: ${value} and donation count ${key}`, 89 | ); 90 | }; 91 | new Map(Object.entries(dateDonations)).forEach(logDateElements); 92 | t1 = now(); 93 | console.timeEnd('total donations for each month'); 94 | console.log( 95 | `Performance now donations per month timing: ` + 96 | (t1 - t0).toFixed(3) + 97 | `ms`, 98 | ); 99 | }); 100 | -------------------------------------------------------------------------------- /readFileEventStream.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var es = require('event-stream'); 3 | var now = require('performance-now'); 4 | 5 | var totalLines = 0; 6 | var names = []; 7 | var firstNames = []; 8 | var dupeNames = {}; 9 | var dateDonationCount = []; 10 | var dateDonations = {}; 11 | var t0 = now(); 12 | var t1; 13 | var t2 = now(); 14 | var t3; 15 | var t4 = now(); 16 | var t5; 17 | var t6 = now(); 18 | var t7; 19 | 20 | console.time('line count'); 21 | console.time('names'); 22 | console.time('most common first name'); 23 | console.time('total donations for each month'); 24 | 25 | var s = fs 26 | // .createReadStream('test.txt') 27 | .createReadStream('itcont.txt') 28 | // .createReadStream('/Users/pxn5096/Downloads/indiv18/itcont.txt') 29 | .pipe(es.split()) 30 | .pipe( 31 | es 32 | .mapSync(function(line) { 33 | // console.time('line count'); 34 | totalLines++; 35 | 36 | // get all names 37 | var name = line.split('|')[7]; 38 | if (totalLines === 433 || totalLines === 43244) { 39 | names.push(name); 40 | } 41 | 42 | // get all first halves of names 43 | var firstHalfOfName = name.split(', ')[1]; 44 | 45 | if (firstHalfOfName !== undefined) { 46 | firstHalfOfName.trim(); 47 | 48 | // filter out middle initials 49 | if (firstHalfOfName.includes(' ') && firstHalfOfName !== ' ') { 50 | firstName = firstHalfOfName.split(' ')[0]; 51 | firstName.trim(); 52 | firstNames.push(firstName); 53 | dupeNames[firstName] = (dupeNames[firstName] || 0) + 1; 54 | } else { 55 | firstNames.push(firstHalfOfName); 56 | dupeNames[firstHalfOfName] = (dupeNames[firstHalfOfName] || 0) + 1; 57 | } 58 | } 59 | 60 | // year and month 61 | var timestamp = line.split('|')[4].slice(0, 6); 62 | var formattedTimestamp = 63 | timestamp.slice(0, 4) + '-' + timestamp.slice(4, 6); 64 | dateDonationCount.push(formattedTimestamp); 65 | dateDonations[formattedTimestamp] = 66 | (dateDonations[formattedTimestamp] || 0) + 1; 67 | }) 68 | .on('error', function(err) { 69 | console.log('Error while reading file.', err); 70 | }) 71 | .on('end', function() { 72 | console.log('Read entire file.'); 73 | t1 = now(); 74 | console.log(totalLines); 75 | console.timeEnd('line count'); 76 | console.log( 77 | `Performance now line count timing: ` + (t1 - t0).toFixed(3) + `ms`, 78 | ); 79 | 80 | t3 = now(); 81 | console.timeEnd('names'); 82 | console.log( 83 | `Performance now names timing: ` + (t3 - t2).toFixed(3) + `ms`, 84 | ); 85 | 86 | sortedDupeNames = Object.entries(dupeNames); 87 | 88 | sortedDupeNames.sort((a, b) => { 89 | return b[1] - a[1]; 90 | }); 91 | console.log(sortedDupeNames[0]); 92 | t5 = now(); 93 | console.timeEnd('most common first name'); 94 | console.log( 95 | `Performance now first name timing: ` + (t5 - t4).toFixed(3) + `ms`, 96 | ); 97 | const name = sortedDupeNames[0][0]; 98 | const nameOccurrences = sortedDupeNames[0][1]; 99 | console.log( 100 | `The most common name is '${name}' with ${nameOccurrences} occurrences.`, 101 | ); 102 | 103 | // number of donations per month 104 | logDateElements = (key, value, map) => { 105 | console.log( 106 | `Donations per month and year: ${value} and donation count ${key}`, 107 | ); 108 | }; 109 | new Map(Object.entries(dateDonations)).forEach(logDateElements); 110 | t7 = now(); 111 | console.timeEnd('total donations for each month'); 112 | console.log( 113 | `Performance now donations per month timing: ` + 114 | (t7 - t6).toFixed(3) + 115 | `ms`, 116 | ); 117 | }), 118 | ); 119 | -------------------------------------------------------------------------------- /readFileStream.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var readline = require('readline'); 3 | var stream = require('stream'); 4 | var now = require('performance-now'); 5 | 6 | // var instream = fs.createReadStream('test.txt'); 7 | var instream = fs.createReadStream('itcont.txt'); 8 | 9 | var outstream = new stream(); 10 | var rl = readline.createInterface(instream, outstream); 11 | 12 | //get line count for file 13 | var lineCount = 0; 14 | 15 | // create array list of names 16 | var names = []; 17 | 18 | // donations occurring in each month 19 | var dateDonationCount = []; 20 | var dateDonations = {}; 21 | 22 | // list of first names, and most common first name 23 | var firstNames = []; 24 | var dupeNames = {}; 25 | 26 | var t0 = now(); 27 | var t1; 28 | var t2 = now(); 29 | var t3; 30 | var t4 = now(); 31 | var t5; 32 | var t6 = now(); 33 | var t7; 34 | 35 | console.time('line count'); 36 | console.time('names'); 37 | console.time('most common first name'); 38 | console.time('total donations for each month'); 39 | 40 | rl.on('line', function(line) { 41 | // increment line count 42 | lineCount++; 43 | 44 | // get all names 45 | var name = line.split('|')[7]; 46 | names.push(name); 47 | 48 | // get all first halves of names 49 | var firstHalfOfName = name.split(', ')[1]; 50 | if (firstHalfOfName !== undefined) { 51 | firstHalfOfName.trim(); 52 | // filter out middle initials 53 | if (firstHalfOfName.includes(' ') && firstHalfOfName !== ' ') { 54 | firstName = firstHalfOfName.split(' ')[0]; 55 | firstName.trim(); 56 | firstNames.push(firstName); 57 | dupeNames[firstName] = (dupeNames[firstName] || 0) + 1; 58 | } else { 59 | firstNames.push(firstHalfOfName); 60 | dupeNames[firstHalfOfName] = (dupeNames[firstHalfOfName] || 0) + 1; 61 | } 62 | } 63 | 64 | // year and month 65 | var timestamp = line.split('|')[4].slice(0, 6); 66 | var formattedTimestamp = timestamp.slice(0, 4) + '-' + timestamp.slice(4, 6); 67 | dateDonationCount.push(formattedTimestamp); 68 | dateDonations[formattedTimestamp] = 69 | (dateDonations[formattedTimestamp] || 0) + 1; 70 | }); 71 | 72 | rl.on('close', function() { 73 | // total line count 74 | t1 = now(); 75 | console.log(lineCount); 76 | console.timeEnd('line count'); 77 | console.log( 78 | `Performance now line count timing: ` + (t1 - t0).toFixed(3) + `ms`, 79 | ); 80 | 81 | // names at various points in time 82 | console.log(names[432]); 83 | console.log(names[43243]); 84 | t3 = now(); 85 | console.timeEnd('names'); 86 | console.log(`Performance now names timing: ` + (t3 - t2).toFixed(3) + `ms`); 87 | 88 | // most common first name 89 | var sortedDupeNames = Object.entries(dupeNames); 90 | 91 | sortedDupeNames.sort((a, b) => { 92 | return b[1] - a[1]; 93 | }); 94 | console.log(sortedDupeNames[0]); 95 | t5 = now(); 96 | console.timeEnd('most common first name'); 97 | console.log( 98 | `Performance now first name timing: ` + (t5 - t4).toFixed(3) + `ms`, 99 | ); 100 | const name = sortedDupeNames[0][0]; 101 | const nameOccurrences = sortedDupeNames[0][1]; 102 | console.log( 103 | `The most common name is '${name}' with ${nameOccurrences} occurrences.`, 104 | ); 105 | 106 | // number of donations per month 107 | logDateElements = (key, value, map) => { 108 | console.log( 109 | `Donations per month and year: ${value} and donation count ${key}`, 110 | ); 111 | }; 112 | new Map(Object.entries(dateDonations)).forEach(logDateElements); 113 | t7 = now(); 114 | console.timeEnd('total donations for each month'); 115 | console.log( 116 | `Performance now donations per month timing: ` + 117 | (t7 - t6).toFixed(3) + 118 | `ms`, 119 | ); 120 | }); 121 | -------------------------------------------------------------------------------- /test.txt: -------------------------------------------------------------------------------- 1 | C00177436|N|M2|P|201702039042410893|15|IND|MAKER, SCOTT T.|NORTH YARMOUTH|ME|040976952|UNUM|SVP, DEPUTY GENERAL COUNSEL, BUSINESS|01312017|384||PR2260663445050|1147350||P/R DEDUCTION ($192.00 BI-WEEKLY)|4020820171370029336 2 | C00095109|N|M2|P|201702109049341736|15|IND|LEFKIN, PETER|WASHINGTON|DC|200162218|ALLIANZ LIFE NORTH AMERICA|SR. V.P. - GOVERNMENT & EXTERNAL AFFAI|01312017|380||PR282813516201|1148519||P/R DEDUCTION ($190.00 SEMI-MONTHLY)|4021020171370599168 3 | C00095109|N|M2|P|201702109049341736|15|IND|BURNS, THOMAS|EXCELSIOR|MN|553318325|ALLIANZ LIFE NORTH AMERICA|CHIEF DISTRIBUTION OFFICER|01312017|240||PR283051916201|1148519||P/R DEDUCTION ($120.00 SEMI-MONTHLY)|4021020171370599169 4 | C00095109|N|M2|P|201702109049341736|15|IND|WHITE, WALTER|STILLWATER|MN|550822150|ALLIANZ LIFE NORTH AMERICA|CHIEF ADMINISTRATIVE OFFICER|01312017|400||PR301778416201|1148519||P/R DEDUCTION ($200.00 SEMI-MONTHLY)|4021020171370599170 5 | C00095109|N|M2|P|201702109049341737|15|IND|CEPEK, GRETCHEN|EDINA|MN|554362650|ALLIANZ LIFE NORTH AMERICA|LEGAL OPERATIONS/ATTORNEY|01312017|240||PR340591816201|1148519||P/R DEDUCTION ($120.00 SEMI-MONTHLY)|4021020171370599171 6 | C00399063|N|M2|P|201702109049341767|15|IND|CHAUVETTE, DEREK WILLIAM|SHAKER HEIGHTS|OH|441223447|KEYBANK NATIONAL ASSOCIATION|HEAD OF PUBLIC SECTOR|01312017|230||PR54372113107|1148536||P/R DEDUCTION ($115.38 BI-WEEKLY)|4021020171370599172 7 | C00399063|N|M2|P|201702109049341767|15|IND|PAINE III, ANDREW J|CLEVELAND HEIGHTS|OH|441184027|KEYBANC CAPITAL MARKETS INC.|CO-HEAD CORPORATE BANK|01312017|384||PR56880213107|1148536||P/R DEDUCTION ($192.30 BI-WEEKLY)|4021020171370599173 8 | C00412098|N|M2|P|201702109049342765|15|IND|BUCKNER, CHARLES E.|BAKERSFILED|CA|93389|JOINT HEIRS FOOD CORPORATION|PRESIDENT|01062017|600||3170|1148557|||4021020171370599544 9 | C00412098|N|M2|P|201702109049342765|15|IND|KOHL, LARUE|GUNTERSVILLE|AL|35976|KING KOHL FOOD SERVICES, INC.|FRANCHISEE|01042017|500||3165|1148557|||4021020171370599545 10 | C00412098|N|M2|P|201702109049342765|15|IND|LAMBOS, GEORGE|MASSILLON|OH|44646|KENDALL HOUSE INC|PRESIDENT|01042017|2000||3159|1148557|||4021020171370599546 11 | C00412098|N|M2|P|201702109049342766|15|IND|MCSWAIN, LYNN|PARRISH|FL|34219|FERBER AND SONS, INC.|CFO|01052017|400||3166|1148557|||4021020171370599547 12 | C00412098|N|M2|P|201702109049342766|15|IND|OVERCASH, ERIC|KANNAPOLIS|NC|28081|O INC|CEO|01042017|800||3161|1148557|||4021020171370599548 13 | C00412098|N|M2|P|201702109049342766|15|IND|PEEPLES, VICTOR|MADISON|GA|30650|STAR BRANDS IV|FRANCHISEE|01052017|1500||3167|1148557|||4021020171370599549 14 | C00412098|N|M2|P|201702109049342767|15|IND|POTTER, NICHOLAS|FAYETTEVILLE|NC|28301|PARRIS & POTTER MANAGEMENT CORP|VICE PRESIDENT|01042017|500||3163|1148557|||4021020171370599550 15 | C00412098|N|M2|P|201702109049342767|15|IND|SANDERS, DOYLE|ADA|OK|74820|KFC OF OKLAHOMA INC|FRANCHISEE|01042017|250||3164|1148557|||4021020171370599551 16 | C00412098|N|M2|P|201702109049342767|15|IND|SHELTON, BONNY B.|DANVILLE|VA|24541|BACON ENTERPRISES, INC.|PRESIDENT|01312017|1100||3157|1148557|||4021020171370599552 17 | C00412098|N|M2|P|201702109049342768|15|IND|SIBERT, SAMUEL L.|KIRKLAND|WA|98072|NORTHWEST RESTAURANTS INC.|CEO|01042017|5000||3162|1148557|||4021020171370599553 18 | C00412098|N|M2|P|201702109049342768|15|IND|WEST, CHARLES T.|LAUREL|MS|39442|WEST QUALITY FOOD SERVICE INC|FRANCHISEE|01312017|1000||3158|1148557|||4021020171370599554 19 | C00401224|A|M3|P|201804039098807622|24T|IND|MOORE, JOHN|NEW YORK|NY|10011|||02132017|-15|C00437277|SB28A_70206576|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR JEFF MERKLEY FOR OREGON (C00437277)|4043020181532952440 20 | C00401224|A|M3|P|201804039098807623|24T|IND|MOORE, KARYL|PRESCOTT|AZ|86301|||02072017|-25|C00500843|SB28A_70745018|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR ELIZABETH FOR MA, INC. (C00500843)|4043020181532952442 21 | C00401224|A|M3|P|201804039098807623|22Y|IND|MOORE, LINDA|BETHLEHEM|GA|30620|||02012017|1||SB28A_67404159|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR ACTBLUE (C00401224)|4043020181532952444 22 | C00401224|A|M3|P|201804039098807623|24T|IND|MOORE, LINDA|BETHLEHEM|GA|30620|||02012017|-5|C00000935|SB28A_67404156|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR DCCC (C00000935)|4043020181532952446 23 | C00401224|A|M3|P|201804039098808867|22Y|IND|THIBODEAU, MARILYN R.|HOUSTON|TX|77023|||02042017|5||SB28A_62793474|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR ACTBLUE (C00401224)|4043020181532959927 24 | C00401224|A|M3|P|201804039098808868|24T|IND|THIBODEAU, MARILYN R.|HOUSTON|TX|77023|||02042017|-15|C00213512|SB28A_67402788|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR NANCY PELOSI FOR CONGRESS (C00213512)|4043020181532959929 25 | C00401224|A|M3|P|201804039098808868|24T|IND|THIBODEAU, MARILYN R.|HOUSTON|TX|77023|||02042017|-15|C00213512|SB28A_65863533|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR NANCY PELOSI FOR CONGRESS (C00213512)|4043020181532959931 --------------------------------------------------------------------------------