"WC -l" এর চেয়ে দ্রুততর কিছু দরকার


12

সত্যিই 1 জিবি এর মতো বড় ফাইলের wc -lজন্য ধীর হতে পারে। আমাদের কাছে কোনও নির্দিষ্ট ফাইলের জন্য নতুন লাইনের সংখ্যা গণনা করার দ্রুত উপায় আছে?


25
দ্রুত ডিস্ক কিনবেন? প্রদত্ত 0x0Aইনপুটটির প্রতিটি বাইট অবশ্যই এর ইনসেসের জন্য পরীক্ষা করা উচিত , I / O সন্দেহাতীতভাবে বাধা।
ট্রিগার করুন

2
যদি আপনার wcঅত্যধিক ওভারহেড থাকার সন্দেহ হয় তবে আপনি নিজের প্রয়োগ করার চেষ্টা করতে পারেন foreach byte in file: if byte == '\n': linecount++। যদি সি বা এসেম্বলারের মধ্যে প্রয়োগ করা হয় তবে আমি মনে করি না এটি কোনও দ্রুত অগ্রগতি লাভ করবে, সম্ভবত কোনও আরটিওএসে কার্নেল স্পেসে সর্বাধিক অগ্রাধিকার সহ (বা এমনকি এটির জন্য একটি বিঘ্নও ব্যবহার করুন - আপনি কেবল সিস্টেমের সাথে অন্য কিছু করতে পারবেন না)। .. ঠিক আছে, আমি digress ;-))
মারফি

3
এবং কেবল স্কেলের অনুভূতি পেতে আমি time wc -l some_movie.aviএকটি আনচড ফাইলটিতে একটি দ্রুত করেছি , যার ফলস্বরূপ 5172672 some_movie.avi -- real 0m57.768s -- user 0m0.255s -- sys 0m0.863s। যা মূলত @ থ্রিগকে সঠিক প্রমাণ করে, I / O এক্ষেত্রে আপনার অভিনয়কে ছড়িয়ে দেয়।
মারফি

10
এটি ডিস্ক আইও বোতল নালাকে দেখানোর সর্বোত্তম উপায়, time wc -l some_large_file_smaller_than_cacheদ্রুত পরপর দু'বার করুন এবং দ্বিতীয় ক্রিয়াকলাপটি কত দ্রুত হয় তা দেখুন time wc -l some_large_file_larger_than_cacheএবং তারপরে দেখুন কীভাবে সময় রানের মধ্যে পরিবর্তন হয় না। এখানে 0 280MB ফাইলের জন্য সময়টি 1.7 সেকেন্ড থেকে 0.2 সেকেন্ডে চলে যায়, তবে 2 জিবি ফাইলের জন্য এটি উভয় সময় 14 সেকেন্ড হয়।
এইটবিটটনি

1
আপনার জন্য কত ধীর গতি? কি /usr/bin/time wc -l <file>বলে? আপনার হার্ডওয়্যার কি? আপনি যদি বার বার কমান্ডটি চালনা করেন তবে এটি দ্রুত হয়? আমাদের সত্যই আরও তথ্যের প্রয়োজন;)
মার্সেলেম

উত্তর:


21

আপনি সি তে লিখতে চেষ্টা করতে পারেন :

#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(){
  char buf[BUFSIZ];
  int nread;
  size_t nfound=0;
  while((nread=read(0, buf, BUFSIZ))>0){
    char const* p;
    for(p=buf; p=memchr(p,'\n',nread-(p-buf)); nfound++,p++) {;}
  }
  if(nread<0) { perror("Error"); return 1; }
  printf("%lu\n", nfound);
  return 0;
}

যেমন সংরক্ষণ করুন, যেমন wcl.cসংকলন, সহ gcc wcl.c -O2 -o wclএবং সাথে চালানো

<yourFile ./wcl

এটি আমার সিস্টেমে 1GB ফাইলে প্রায় 370 মিমিগুলিতে ছড়িয়ে ছিটিয়ে থাকা নিউলাইনগুলি খুঁজে পেয়েছে (পুনরাবৃত্ত রান)। (বাফার মাপ বাড়ানো সময়কে কিছুটা বাড়িয়ে দেয়, যা প্রত্যাশিত - BUFSIZ সর্বোত্তমের কাছাকাছি হওয়া উচিত)। এটি যে 80 380 ডলার থেকে পাচ্ছি তার সাথে এটি তুলনামূলক wc -l

ম্যামপিং আমাকে প্রায় 280 মিমি সম্পর্কে ভাল সময় দেয় , তবে অবশ্যই এটি বাস্তব ফাইলগুলির মধ্যে সীমাবদ্ধ থাকার সীমাবদ্ধতা রয়েছে (কোনও ফিফস, কোনও টার্মিনাল ইনপুট ইত্যাদি নয়):

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
  struct stat sbuf;
  if(fstat(0, &sbuf)<0){ perror("Can't stat stdin"); return 1; }

  char* buf = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, 0/*stdin*/, 0/*offset*/);
  if(buf == MAP_FAILED){ perror("Mmap error"); return 1; } 

  size_t nread = sbuf.st_size, nfound=0;
  char const* p;
  for(p=buf; p=memchr(p,'\n',nread-(p-buf)); nfound++,p++) {;}

  printf("%lu\n", nfound);
  return 0;
}

আমি আমার পরীক্ষার ফাইলটি এর সাথে তৈরি করেছি:

 $ dd if=/dev/zero of=file bs=1M count=1042 

এবং এর সাথে কয়েকটি পরীক্ষার নিউলাইনগুলি যুক্ত করেছে:

 $ echo >> 1GB 

এবং একটি হেক্স সম্পাদক।


এমএমএপ ফলাফল টিবিএইচ দেখে আমি অবাক হয়েছি। আমি ভাবতাম এমএমপিং পড়া / লেখার চেয়ে দ্রুত, তবে তারপরে আমি কিছু লিনাক্স বেঞ্চমার্ক দেখলাম যা বিপরীত দেখিয়েছিল। দেখে মনে হচ্ছে এটি এক্ষেত্রে খুব সত্য।
পিএসকোকিক

4
এমএমএপি লিনাক্সের উপর আরও ভাল ফলাফল পেতে চলেছে কারণ এটি আজকাল বিশাল পৃষ্ঠাগুলিতে ম্যাপ করবে এবং টিএলবি মিস করবে না স্লোউউউউউউইউউইউউইউউউউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউইউবউইউব।
jthill

পৃথক থ্রেডে (যেমন একটি ওপেনএমপি forলুপের সাহায্যে) ফাইলের বিভিন্ন অংশগুলি পড়ার কিছু সুবিধা থাকতে পারে যাতে একটি থ্রেড ইনপুটটির জন্য অপেক্ষা করে স্থির হয়ে থাকতে পারে। তবে অন্যদিকে, এটি I / O সময়সূচী বাধাগ্রস্থ করতে পারে, তাই আমি সুপারিশ করতে পারি কেবলমাত্র এটি চেষ্টা করা এবং পরিমাপ করা!
টবি স্পিড

read()সংস্করণ পড়তে সম্মতি থেকে লাভবান হতে পারে।
বার্মার

1
টবিস্পাইট হ্যাঁ, মাল্টিথ্রেডিং এটির গতি বাড়িয়ে দিতে পারে। এছাড়াও 2 ^ 16 লুক টেবিলের মাধ্যমে একবারে দুটি বাইট স্ক্যান করে দেখছি আমি এটির সাথে শেষবারের মতো খেলেছি good
PSkocik

18

@Pskocik এর প্রস্তাবিত সমাধানগুলিতে কল করার সংখ্যা হ্রাস করে আপনি উন্নত করতে পারেন read। একটা হয় অনেক কল পড়তে BUFSIZএকটি 1GB ফাইল থেকে খন্ডে। এটি করার স্বাভাবিক পদ্ধতির বিষয়টি বাফারের আকার বাড়িয়ে দেওয়া:

  • কেবল মজাদার জন্য, বাফার-আকারকে 10 বা 100 এর একটি ফ্যাক্টর দ্বারা বাড়ানোর চেষ্টা করুন my আমার ডেবিয়ান 7-এ, BUFSIZ8192। এটি 100 এর ফ্যাক্টর দ্বারা হ্রাস করতে আপনি সম্ভবত 1 এমবি ইনপুট বাফার নিতে পারেন।
  • আরও অনুকূল পদ্ধতির জন্য, অ্যাপ্লিকেশনগুলি ফাইলের মতো বৃহত একটি বাফার বরাদ্দ করতে পারে, যার জন্য একটি একক রিড অপারেশন প্রয়োজন। এটি "ছোট" ফাইলগুলির জন্য যথেষ্ট ভাল কাজ করে (যদিও কিছু পাঠকের মেশিনে 1 জিবি-র বেশি থাকে)।
  • অবশেষে, আপনি মেমরি-ম্যাপযুক্ত I / O নিয়ে পরীক্ষা করতে পারেন, যা বরাদ্দকে যেমন পরিচালনা করে।

বিভিন্ন পদ্ধতির বেঞ্চমার্ক করার সময়, আপনি মনে রাখতে পারেন যে কিছু সিস্টেম (যেমন লিনাক্স) আপনার মেশিনের বেশিরভাগ অব্যবহৃত মেমরিটিকে ডিস্ক ক্যাশে হিসাবে ব্যবহার করে। কিছুক্ষণ আগে (প্রায় 20 বছর আগে, জঘন্য FAQ এ উল্লিখিত ), আমি একটি (খুব ভাল নয়) পেজিং অ্যালগরিদম থেকে অপ্রত্যাশিতভাবে ভাল ফলাফল পেয়ে হতবাক হয়েছি যা আমি একটি পাঠ্য সম্পাদকটিতে স্বল্প-স্মৃতি শর্তকে পরিচালনা করার জন্য গড়ে তুলেছিলাম। এটি আমার কাছে ব্যাখ্যা করা হয়েছিল যে এটি দ্রুত দৌড়েছিল কারণ প্রোগ্রামটি মেমরি বাফারগুলি ফাইলটি পড়ার জন্য কাজ করছিল এবং কেবল যদি ফাইলটি পুনরায় পড়তে বা লিখিত হয় তবেই গতিতে কোনও পার্থক্য থাকবে।

এটি একই ক্ষেত্রে প্রযোজ্য mmap(FAQ এ অন্তর্ভুক্ত করার জন্য এখনও আমার করণীয় তালিকায় থাকা অন্য ক্ষেত্রে, একজন বিকাশকারী এমন দৃশ্যে খুব ভাল ফলাফলের রিপোর্ট করেছিলেন যেখানে ডিস্ক ক্যাশে উন্নতির আসল কারণ ছিল)। উন্নত মানদণ্ডগুলি ভাল (বা খারাপ) পারফরম্যান্সের কারণগুলি বিশ্লেষণ করতে সময় এবং যত্ন নেয়।

আরও পড়া:


2
আপনি একটি নির্দিষ্ট প্রান্তিকের উপরে বাফার আকারের প্রভাবকে বেশি মূল্যায়ন করছেন। সাধারণত, 4KB-ish এর বাইরে বাফারের আকার বাড়ানো খুব বেশি সহায়তা করে না এবং আসলে এটি ক্ষতিকারক হতে পারে কারণ এটি বাফারকে এল 1 ক্যাশে থেকে বের করে দিতে পারে। আমার মেশিনে, dd1MB বাফার ব্যবহার করে পরীক্ষা করা 8KB এর চেয়ে ধীর । ডাব্লুসিটির জন্য 8 কেবি ডিফল্ট মানটি আসলে বেশ ভালভাবে বেছে নেওয়া হয়েছে, এটি সিস্টেমের বৃহত পরিসরের জন্য অনুকূলের কাছাকাছি থাকবে।
মার্সেলেম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.