সি #: ফাইল.আরেডলাইনস () বনাম ফাইল.আডএললাইনস () - এবং কেন আমার যত্ন করা উচিত?

কয়েক সপ্তাহ আগে, আমি এবং আমি যে দুটি টিম নিয়ে কাজ করছি তার মধ্যে দুটি বড় টেক্সট ফাইল প্রক্রিয়াজাত করার দক্ষ উপায়গুলি নিয়ে আলোচনা শুরু করে।

এটি পূর্ববর্তী সময়ে এই বিষয়টি সম্পর্কে এবং বিশেষত সি # তে ফলন ফেরতের ব্যবহার সম্পর্কে (যা সম্ভবত আমি ভবিষ্যতের ব্লগ পোস্টে আলোচনা করব) কিছু অন্যান্য আলোচনার সূত্রপাত করেছিল। সুতরাং, আমি ভেবেছিলাম যে বড় অঙ্কের ডেটা প্রক্রিয়া করার ক্ষেত্রে সি # কার্যকরভাবে কীভাবে স্কেল করতে পারে তা প্রদর্শন করা ভাল চ্যালেঞ্জ হবে।

চ্যালেঞ্জ

সুতরাং, আলোচনার মধ্যে থাকা সমস্যাটি হ'ল:

  • ধরুন এখানে একটি বৃহত সিএসভি ফাইল রয়েছে, প্রারম্ভিকদের জন্য ~ 500MB বলুন
  • প্রোগ্রামটি অবশ্যই ফাইলের প্রতিটি লাইনের মধ্য দিয়ে যেতে হবে, এটি বিশ্লেষণ করবে এবং কিছু মানচিত্র তৈরি করবে / ভিত্তিক গণনা হ্রাস করবে

এবং আলোচনার এই পর্যায়ে প্রশ্নটি হ'ল:

এই লক্ষ্যটি অর্জন করতে সক্ষম কোডটি লেখার সর্বাধিক দক্ষ উপায় কোনটি? সাথে মেনে চলার সময়:
i) ব্যবহৃত মেমরির পরিমাণ হ্রাস করুন এবং
ii) প্রোগ্রামের কোডের লাইনগুলি হ্রাস করুন (অবশ্যই একটি যুক্তিসঙ্গত পরিমাণে)

যুক্তিটির স্বার্থে, আমরা স্ট্রিমরিডার ব্যবহার করতে পারতাম, তবে এটির প্রয়োজনে আরও কোড লিখতে হবে এবং প্রকৃতপক্ষে সি # এর মধ্যে ইতিমধ্যে ফাইল e রিডআললাইনস () এবং ফাইল.আরডলাইনস () সুবিধার পদ্ধতি রয়েছে। সুতরাং আমাদের সেগুলি ব্যবহার করা উচিত!

আমাকে কোডটি দেখান

উদাহরণের স্বার্থে, আসুন একটি প্রোগ্রাম বিবেচনা করি যা:

  1. ইনপুট হিসাবে একটি পাঠ্য ফাইল নেয় যেখানে প্রতিটি লাইন একটি পূর্ণসংখ্যা হয়
  2. ফাইলের সমস্ত সংখ্যার যোগফল গণনা করে

এই উদাহরণের স্বার্থে, আমরা বেশিরভাগ বৈধতা বার্তা এড়িয়ে যাব :-)

সি # এ নিম্নলিখিত কোড দ্বারা সম্পন্ন করা যেতে পারে:

var sumOfLines = File.ReadAllLines (ফাইলপথ)
    । নির্বাচন করুন (লাইন => ইন্ট। পার্স (লাইন))
    .Sum ()

খুব সহজ, তাই না?

আমরা যখন একটি বড় ফাইল দিয়ে এই প্রোগ্রামটি ফিড করি তখন কী হয়?

যদি আমরা এই প্রোগ্রামটি একটি 100MB ফাইল প্রক্রিয়া করতে চালিত করি তবে আমরা যা পাই এটি এটি:

  • 2 গিগাবাইট র‌্যাম এই কম্পিউটিংটি সম্পূর্ণ করতে মেমরি গ্রাস করেছে
  • প্রচুর জিসি (প্রতিটি হলুদ আইটেম একটি জিসি চালানো হয়)
  • কার্যকর করা 18 সেকেন্ড
বিটিডাব্লু, এই কোডটিতে একটি 500 এমবি ফাইল খাওয়ানোর ফলে প্রোগ্রামটি আউটঅফমিউরিঅ্যাক্সপশন ফান দিয়ে ক্র্যাশ হয়ে গেছে, তাই না?

এবার আসুন এর পরিবর্তে ফাইলটি পড়ুন

আসুন ফাইলটি ফাইলের জন্য ফাইলটি পড়ুন কোডটি পরিবর্তন করুন Aআরডলাইনস () পড়ুন এবং দেখুন এটি কীভাবে চলে যায়:

var sumOfLines = File.ReadLines (ফাইলপথ)
    । নির্বাচন করুন (লাইন => ইন্ট। পার্স (লাইন))
    .Sum ()

এটি চালানোর সময়, আমরা এখন পাই:

  • 2 এমবি (!!) এর পরিবর্তে 12 এমবি র‌্যাম গ্রহন করা হয়েছে
  • মাত্র 1 জিসি চালায়
  • 18 এর পরিবর্তে 10 সেকেন্ড শেষ করতে হবে

ইহা কি জন্য ঘটিতেছে?

টিএল; ডিআর এর মূল পার্থক্যটি হ'ল ফাইল.আরডএললাইনস () একটি স্ট্রিং তৈরি করছে [] যা ফাইলের প্রতিটি লাইন থাকে, পুরো ফাইলটি লোড করার জন্য পর্যাপ্ত মেমরির প্রয়োজন হয়; ফাইলের বিপরীতে e রিডলাইনস () যা একবারে প্রতিটি লাইনে প্রোগ্রাম ফিড করে, একটি লাইন লোড করার জন্য কেবল মেমরির প্রয়োজন।

আরও কিছু বিশদে:

ফাইল.আরেডলাইনস () পুরো ফাইলটি একবারে পড়ে এবং একটি স্ট্রিং দেয় [] যেখানে অ্যারের প্রতিটি আইটেম ফাইলের লাইনের সাথে মিলে যায়। এর অর্থ এই যে ফাইলটি থেকে বিষয়বস্তুগুলি লোড করতে প্রোগ্রামটির ফাইলের আকারের মতো মেমরির প্রয়োজন। প্লাসে সমস্ত স্ট্রিং উপাদানগুলি পার্স করার জন্য প্রয়োজনীয় মেমরিটি যোগ করুন এবং তারপরে যোগফল () গণনা করুন

অন্যদিকে, ফাইল.আরডলাইনস () ফাইলটিতে একটি গণক তৈরি করে, এটি লাইন-লাইন পড়ে (আসলে স্ট্রিমরিডার ব্যবহার করে e রিডলাইন ())। এর অর্থ হ'ল প্রতিটি লাইন পঠিত, রূপান্তরিত এবং একটি রেখা-হতে-রেখা মোডে আংশিক যোগে যুক্ত করা হয়।

উপসংহার

এই বিষয়টিকে নিম্ন-স্তরের বাস্তবায়ন বিশদ হিসাবে মনে হতে পারে তবে এটি আসলে খুব গুরুত্বপূর্ণ কারণ এটি একটি বড় ডেটা সেট খাওয়ানোর পরে কোনও প্রোগ্রাম কীভাবে স্কেল হবে তা নির্ধারণ করে।

সফ্টওয়্যার বিকাশকারীদের পক্ষে এই ধরণের পরিস্থিতি সম্পর্কে ভবিষ্যদ্বাণী করতে সক্ষম হওয়া গুরুত্বপূর্ণ, কারণ কেউ কখনই বুঝতে পারে না যে কেউ যদি কোনও বৃহত ইনপুট সরবরাহ করতে চলেছে যা উন্নয়নের পর্যায়ে আগে থেকে প্রত্যাশিত ছিল না।

এছাড়াও, লিনকুই এই দুটি দৃশ্যকে নির্বিঘ্নে পরিচালনা করতে এবং মানগুলির "স্ট্রিমিং" সরবরাহ করে এমন কোড সহ কার্যকর দক্ষতা সরবরাহ করার জন্য যথেষ্ট নমনীয়।

এর অর্থ হ'ল সমস্ত কিছুই একটি তালিকা <টি> বা একটি টি [] হওয়ার দরকার নেই যা বোঝায় যে পুরো ডেটা সেট মেমরিতে লোড হয়। আইনিউমেবল <টি> ব্যবহার করে আমরা আমাদের কোডটিকে এমন পদ্ধতিগুলির সাথে ব্যবহারের জন্য জেনেরিক করি যা মেমরিতে সেট করা পুরো ডেটা সরবরাহ করে বা "স্ট্রিমিং" মোডে মান সরবরাহ করে।