টোললিস্ট () কল করার সময় কোনও পারফরম্যান্স প্রভাব আছে?


139

ব্যবহার করার সময় ToList(), এমন কোনও পারফরম্যান্স প্রভাব রয়েছে যা বিবেচনা করা দরকার?

আমি একটি ডিরেক্টরি থেকে ফাইলগুলি পুনরুদ্ধার করার জন্য একটি কোয়েরি লিখছিলাম, যা কোয়েরি:

string[] imageArray = Directory.GetFiles(directory);

তবে, যেহেতু আমি List<>পরিবর্তে কাজ করতে পছন্দ করি তাই আমি সিদ্ধান্ত নিয়েছিলাম ...

List<string> imageList = Directory.GetFiles(directory).ToList();

সুতরাং, এরকম কোনও রূপান্তর করার সিদ্ধান্ত নেওয়ার সময় এমন কিছু পারফরম্যান্স প্রভাব রয়েছে যা বিবেচনা করা উচিত - বা কেবলমাত্র বিপুল সংখ্যক ফাইলের সাথে ডিল করার সময় বিবেচনা করা উচিত? এটি কি নগণ্য রূপান্তর?


উত্তরটিও এখানে জানতে আগ্রহী 1 এই প্রোগ্রামটিতে যদি না অ্যাপ্লিকেশানের কার্যদক্ষতা সমালোচনামূলক, আমি মনে করি আমি সবসময় ব্যবহার করতে চাই List<T>একটি পক্ষে T[]যদি এটা কোড আরো যৌক্তিক / পাঠযোগ্য / রক্ষণীয় (যদি না অবশ্যই রূপান্তর তোলে হয়েছিল যার ফলে লক্ষণীয় কর্মক্ষমতা সমস্যা যে ক্ষেত্রে আমি পুনরায় চাই আমি এটি অনুমান করুন)।
সেপ্টেস্টার

একটি অ্যারে থেকে একটি তালিকা তৈরি করা অত্যন্ত সস্তা হওয়া উচিত।
লেপি

2
@ সেপস্টার আমি কেবল ডেটা টাইপ নির্দিষ্টভাবে নির্দিষ্ট করি যেমন আমার কোনও কাজ করা দরকার। যদি আমাকে কল করতে না হয় Addবা Remove, আমি এটি IEnumerable<T>(বা আরও ভাল var) হিসাবে ছেড়ে দেব
pswg

4
আমি মনে করি, এক্ষেত্রে EnumerateFilesপরিবর্তে কল করা ভাল GetFiles, সুতরাং কেবল একটি অ্যারে তৈরি করা হবে।
টুকাফ

3
GetFiles(directory), যেমন এটি। নেট এ বর্তমানে প্রয়োগ করা হয়েছে, বেশ কিছু করে new List<string>(EnumerateFiles(directory)).ToArray()। সুতরাং GetFiles(directory).ToList()একটি তালিকা তৈরি করে, সে থেকে একটি অ্যারে তৈরি করে, তারপরে আবার একটি তালিকা তৈরি করে। 2 কে যেমন বলেছেন, আপনার EnumerateFiles(directory).ToList()এখানে করা পছন্দ করা উচিত ।
জোড়েন

উত্তর:


178

IEnumerable.ToList()

হ্যাঁ, এর IEnumerable<T>.ToList()কার্যকারিতা প্রভাব ফেলবে, এটি একটি ও (এন) অপারেশন যদিও এটির জন্য সম্ভবত সম্পাদন সমালোচনামূলক ক্রিয়াকলাপগুলিতে মনোযোগ প্রয়োজন।

ToList()অপারেশন ব্যবহার করবে List(IEnumerable<T> collection)কন্সট্রাকটর। এই নির্মাতাকে অবশ্যই অ্যারের একটি অনুলিপি তৈরি করতে হবে (আরও সাধারণভাবে IEnumerable<T>), না হলে ভবিষ্যতে মূল অ্যারের পরিবর্তনগুলি উত্সেও পরিবর্তিত হবে T[]যা সাধারণত কাঙ্ক্ষিত হবে না।

আমি এটির পুনরাবৃত্তি করতে চাই শুধুমাত্র একটি বিশাল তালিকার সাথে একটি পার্থক্য তৈরি করবে, মেমরির খণ্ডগুলি অনুলিপি করা সম্পাদন করা বেশ দ্রুত অপারেশন।

সহজ টিপস, AsবনামTo

আপনি লিনকিউতে লক্ষ্য করবেন যে কয়েকটি পদ্ধতি রয়েছে As(যেমন AsEnumerable()) এবং To( যেমন ) দিয়ে শুরু হয় ToList()। যে পদ্ধতিগুলি দিয়ে শুরু হয় তাদের Toউপরের মতো রূপান্তর প্রয়োজন (অর্থাত্ পারফরম্যান্সে প্রভাব ফেলতে পারে), এবং যে পদ্ধতিগুলি দিয়ে শুরু হয় Asনা এবং কেবল কিছু কাস্ট বা সহজ অপারেশন প্রয়োজন।

অতিরিক্ত বিবরণ List<T>

List<T>আপনার আগ্রহের ক্ষেত্রে কীভাবে কাজ করে সে সম্পর্কে এখানে আরও কিছু বিশদ দেওয়া হল :)

List<T>ডায়নামিক অ্যারে নামে একটি কনস্ট্রাক্টও ব্যবহার করে যার চাহিদা অনুসারে পুনরায় আকার দেওয়া দরকার, এই পুনরায় আকারের ইভেন্টটি পুরানো অ্যারের সামগ্রীগুলি নতুন অ্যারে অনুলিপি করে। সুতরাং এটি ছোট থেকে শুরু হয় এবং প্রয়োজনে আকারে বৃদ্ধি পায়

এটিতে Capacityএবং Countবৈশিষ্ট্যগুলির মধ্যে পার্থক্য List<T>Capacityপর্দার পিছনে অ্যারের আকার বোঝায়, যা সর্বদা Countআইটেমের সংখ্যা । সুতরাং তালিকায় যখন কোনও আইটেম যুক্ত করা হবে, অতীত বাড়িয়ে দিন , তার আকার দ্বিগুণ হয়ে যায় এবং অ্যারের অনুলিপি করা হয়।List<T><= CapacityCapacityList<T>


2
আমি কেবলমাত্র সেই List(IEnumerable<T> collection)কনস্ট্রাক্টর চেকগুলিকে জোর দিতে চেয়েছিলাম যদি সংগ্রহের প্যারামিটার হয় ICollection<T>এবং ঠিক তখনই প্রয়োজনীয় আকারের সাথে একটি নতুন অভ্যন্তরীণ অ্যারে তৈরি করে। যদি প্যারামিটার সংগ্রহ না ICollection<T>হয় তবে কনস্ট্রাক্টর এর মাধ্যমে পুনরাবৃত্তি করে এবং Addপ্রতিটি উপাদানকে কল করে।
জাস্টিনাস সিমানাভিসিয়াস

এটি লক্ষণীয় যে আপনি প্রায়শই ToList () কে বিভ্রান্তিকরভাবে দাবি করা অপারেশন হিসাবে দেখতে পারেন। আপনি যখন একটি মূল << থ্রোঘা লিনকুই ক্যোয়ারী তৈরি করেন তখন এটি ঘটে happens লিনক ক্যোয়ারী নির্মিত হলেও কার্যকর করা হয়নি। টোলিস্টকে কল করা () কোয়েরিটি চালাবে এবং তাই সংস্থান সংস্থান হিসাবে মনে হবে - তবে এটি অনুসন্ধানটি নিখুঁত এবং টোলিস্ট () অপারেশন নয় (যদি এটি সত্যই বিশাল তালিকা না থাকে)
নৃত্যশিল্পী 42

36

লিস্টে () কল করার সময় কোনও পারফরম্যান্স প্রভাব আছে?

হ্যা অবশ্যই. তাত্ত্বিকভাবে এমনকি i++পারফরম্যান্সের প্রভাবও রয়েছে, এটি কয়েক টিকের জন্য প্রোগ্রামটি ধীর করে দেয়।

কি করে .ToList?

আপনি যখন আবেদন করেন তখন .ToListকোড কল করে Enumerable.ToList()যা একটি এক্সটেনশন পদ্ধতি return new List<TSource>(source)। সংশ্লিষ্ট কন্সট্রাক্টরের সবচেয়ে খারাপ পরিস্থিতিতে এটি আইটেমের ধারক হয়ে যায় এবং একে একে একে একে নতুন ধারক হিসাবে যুক্ত করে। সুতরাং এর আচরণ কর্মক্ষমতা উপর সামান্য প্রভাবিত করে। আপনার অ্যাপ্লিকেশনটির পারফরম্যান্স বোতলের ঘাড় হওয়া অসম্ভব।

প্রশ্নের কোডটিতে কী সমস্যা আছে

Directory.GetFilesফোল্ডারটির মধ্য দিয়ে যায় এবং সমস্ত ফাইলের নাম তাত্ক্ষণিকভাবে মেমরিতে ফিরিয়ে দেয় , এটির সম্ভাব্য ঝুঁকি রয়েছে যে স্ট্রিং [] এর অনেক বেশি মেমরির ব্যয় হয়, সবকিছু ধীর করে দেয়।

তখন কী করা উচিত

এটা নির্ভর করে. যদি আপনি (পাশাপাশি আপনার ব্যবসায়িক যুক্তি) গ্যারান্টি দিয়ে থাকেন যে ফোল্ডারে ফাইলের পরিমাণ সর্বদা ছোট থাকে তবে কোডটি গ্রহণযোগ্য। তবে এটি এখনও অলস সংস্করণটি ব্যবহার করার পরামর্শ দেওয়া হয়েছে: Directory.EnumerateFilesসি # 4 এ। এটি অনেকগুলি কোয়েরির মতো যা অবিলম্বে কার্যকর করা হবে না, আপনি এটিতে আরও প্রশ্ন যুক্ত করতে পারেন:

Directory.EnumerateFiles(myPath).Any(s => s.Contains("myfile"))

যার নামটিতে "মাইফিল" রয়েছে এমন একটি ফাইল খুঁজে পাওয়া মাত্রই পাথ অনুসন্ধান বন্ধ করবে । এটি সম্ভবত একটি ভাল পারফরম্যান্স আছে .GetFiles


19

লিস্টে () কল করার সময় কোনও পারফরম্যান্স প্রভাব আছে?

হ্যা এখানে. এক্সটেনশন পদ্ধতিটি ব্যবহার করে উত্স সংগ্রহ থেকে Enumerable.ToList()একটি নতুন List<T>অবজেক্ট তৈরি করা হবে IEnumerable<T>যার অবশ্যই কার্যকারিতা প্রভাব রয়েছে।

তবে বুঝতে List<T>পারফরম্যান্সের প্রভাবটি উল্লেখযোগ্য কিনা তা নির্ধারণ করতে আপনাকে সহায়তা করতে পারে।

List<T>T[]তালিকার উপাদানগুলি সঞ্চয় করতে একটি অ্যারে ( ) ব্যবহার করে । অ্যারেগুলি একবার বরাদ্দ পেলে বাড়ানো যায় না তাই List<T>তালিকার উপাদানগুলি সংরক্ষণ করার জন্য একটি ওজন আকারের অ্যারে ব্যবহার করবে। List<T>আকারগুলি ছাড়িয়ে যখন অন্তর্নিহিত অ্যারেটি বাড়বে তখন একটি নতুন অ্যারে বরাদ্দ করতে হবে এবং তালিকাটি বাড়ার আগে পুরানো অ্যারের সামগ্রীগুলি নতুন বড় অ্যারেতে অনুলিপি করতে হবে।

যখন একটি থেকে নতুন নির্মিত List<T>হয় তখন IEnumerable<T>দুটি ক্ষেত্রে থাকে:

  1. উত্স সংগ্রহের প্রয়োগগুলি ICollection<T>: তারপরে উত্স সংগ্রহের ICollection<T>.Countসঠিক আকার পেতে ব্যবহৃত হয় এবং উত্স সংগ্রহের সমস্ত উপাদান ব্যাকিং অ্যারে ব্যবহার করে অনুলিপি করার আগে একটি ম্যাচিং ব্যাকিং অ্যারে বরাদ্দ করা হয় ICollection<T>.CopyTo()। এই অপারেশনটি বেশ দক্ষ এবং সম্ভবত মেমরির ব্লকগুলি অনুলিপি করার জন্য কিছু সিপিইউ নির্দেশিকায় মানচিত্র তৈরি করবে। তবে, পারফরম্যান্সের ক্ষেত্রে মেমরি নতুন অ্যারের জন্য প্রয়োজন এবং সমস্ত উপাদান অনুলিপি করার জন্য সিপিইউ চক্রের প্রয়োজন।

  2. অন্যথায় উত্স সংগ্রহের আকার অজানা এবং এর সূচকটি IEnumerable<T>প্রতিটি উত্স উপাদানকে নতুন করে একবারে যুক্ত করতে ব্যবহৃত হয় List<T>। প্রাথমিকভাবে ব্যাকিং অ্যারেটি খালি থাকে এবং 4 মাপের একটি অ্যারে তৈরি হয়। তারপরে যখন এই অ্যারেটি খুব ছোট হয় তখন আকারটি দ্বিগুণ হয় সুতরাং ব্যাকিং অ্যারেটি এই 4, 8, 16, 32 ইত্যাদির মতো বেড়ে যায় Every এই অপারেশনটি প্রথম ক্ষেত্রেটির তুলনায় অনেক বেশি ব্যয়বহুল যেখানে ঠিক এখনই সঠিক আকারের একটি অ্যারে তৈরি করা যেতে পারে।

    এছাড়াও, যদি আপনার উত্স সংগ্রহে 33 উপাদান রয়েছে তবে তালিকাটি 64 মেশিনের অপচয় করে elements৪ টি উপাদানের অ্যারে ব্যবহার করে শেষ হবে।

আপনার ক্ষেত্রে উত্স সংগ্রহটি এমন একটি অ্যারে যা কার্যকর করে ICollection<T>তাই পারফরম্যান্স প্রভাবটি এমন কিছু নয় যা আপনার উত্স অ্যারেটি খুব বড় না হলে আপনার সম্পর্কে উদ্বিগ্ন হওয়া উচিত। কলিং ToList()কেবল সোর্স অ্যারের অনুলিপি করে একে কোনও List<T>বস্তুতে মুড়িয়ে দেবে । এমনকি দ্বিতীয় মামলার পারফরম্যান্স ছোট সংগ্রহের জন্য উদ্বেগের কিছু নয়।


5

"এমন কোনও পারফরম্যান্স প্রভাব আছে যা বিবেচনা করা দরকার?"

আপনার সুনির্দিষ্ট দৃশ্যের বিষয়টি হ'ল প্রথম এবং প্রধানত পারফরম্যান্স সম্পর্কে আপনার আসল উদ্বেগ হ'ল ড্রাইভের ক্যাশের হার্ড ড্রাইভের গতি এবং দক্ষতা from

যে দৃষ্টিকোণ থেকে, প্রভাব নিশ্চয় বিন্দু যে উপেক্ষণীয় কোন এটি বিবেচনা করা প্রয়োজন নেই।

তবে কেবলমাত্র যদি List<>সম্ভবত আপনাকে আরও উত্পাদনশীল, বা আপনার অ্যালগোরিদমকে আরও বন্ধুত্বপূর্ণ করতে বা অন্য কোনও সুবিধা তৈরি করতে আপনার কাঠামোর বৈশিষ্ট্যগুলির প্রয়োজন হয়। অন্যথায়, আপনি উদ্দেশ্যমূলকভাবে কোনও কারণ ছাড়াই একটি তুচ্ছ পারফরম্যান্স হিট যুক্ত করছেন। কোন ক্ষেত্রে, স্বাভাবিকভাবেই, আপনার এটি করা উচিত নয়! :)


4

ToList()একটি নতুন তালিকা তৈরি করে এবং এতে উপাদানগুলি রেখে দেয় যার অর্থ হচ্ছে যে করার সাথে একটি যুক্ত খরচ রয়েছে ToList()। ছোট সংগ্রহের ক্ষেত্রে এটি খুব লক্ষণীয় ব্যয় হবে না তবে বিশাল সংগ্রহটি টোললিস্ট ব্যবহারের ক্ষেত্রে পারফরম্যান্সের ক্ষতি করতে পারে।

সংগ্রহকে তালিকায় রূপান্তর না করে সাধারণত আপনি টোললিস্ট () ব্যবহার করবেন না যদি না আপনি কাজ করছেন। উদাহরণস্বরূপ যদি আপনি কেবল সংগ্রহের মাধ্যমে পুনরাবৃত্তি করতে চান তবে আপনাকে টোললিস্ট সঞ্চালনের দরকার নেই

আপনি যদি কোনও ডেটা উত্সের বিরুদ্ধে উদাহরণস্বরূপ কোনও ডেটাবেসকে লিনকিউ থেকে এসকিউএল ব্যবহার করে থাকেন তবে টোলিস্ট করার ব্যয় অনেক বেশি কারণ যখন আপনি বিলম্বিত এক্সিকিউশন না করার পরিবর্তে লিনকিউ থেকে এসকিউএল টোললিস্ট ব্যবহার করেন অর্থাৎ প্রয়োজনের সময় লোড আইটেমগুলি (যা উপকারী হতে পারে) অনেক পরিস্থিতিতে) এটি তাত্ক্ষণিকভাবে ডাটাবেস থেকে আইটেমগুলিকে মেমরিতে লোড করে


হারিস: টোলিস্টে কল করার পরে মূল উত্সটির কী হবে তা সম্পর্কে আমি নিশ্চিত নই ()
ট্যালেন্টটিউনার

@ সৌরভ জিসি এটি পরিষ্কার করবেন
PSWg

@ সৌরভ আসল উত্স থেকে কিছুই ঘটবে না। আসল উত্সের উপাদানগুলি নতুন নির্মিত তালিকার দ্বারা উল্লেখ করা হবে
হারিস হাসান

"আপনি যদি কেবল সংগ্রহের মাধ্যমে পুনরাবৃত্তি করতে চান তবে আপনাকে টোললিস্ট সঞ্চালনের দরকার নেই" - সুতরাং আপনার পুনরাবৃত্তিটি কীভাবে করা উচিত?
শার্পসি

4

এটি করা (যেমন) হিসাবে দক্ষ হবে:

var list = new List<T>(items);

আপনি যদি কোনও কনস্ট্রাক্টরের উত্স কোডটি পৃথক করে দেন তবে IEnumerable<T>আপনি দেখতে পাবেন এটি কয়েকটি কাজ করবে:

  • কল করুন collection.Count, সুতরাং যদি collectionএটি হয় তবে IEnumerable<T>এটি কার্যকর করতে বাধ্য করবে। যদি collectionঅ্যারে, তালিকা ইত্যাদি হয় তবে তা হওয়া উচিত O(1)

  • যদি collectionপ্রয়োগ করে ICollection<T>, এটি ICollection<T>.CopyToপদ্ধতিটি ব্যবহার করে একটি অভ্যন্তরীণ অ্যারে আইটেমগুলি সংরক্ষণ করবে । এটা তোলে উচিত হবে O(n), হচ্ছে nসংগ্রহের দৈর্ঘ্য।

  • যদি collectionপ্রয়োগ না করা ICollection<T>হয় তবে এটি সংগ্রহের আইটেমগুলির মাধ্যমে পুনরাবৃত্তি হবে এবং এগুলি একটি অভ্যন্তরীণ তালিকায় যুক্ত করবে।

সুতরাং, হ্যাঁ, এটি আরও মেমরি গ্রাস করবে, যেহেতু এটি একটি নতুন তালিকা তৈরি করতে হবে এবং সবচেয়ে খারাপ ক্ষেত্রে এটি হবেO(n) , কারণ এটি collectionপ্রতিটি উপাদানটির একটি অনুলিপি তৈরির মাধ্যমে পুনরাবৃত্তি করবে ।


3
বন্ধ করুন, 0(n)যেখানে nমূল সংগ্রহের স্ট্রিংয়ের মোট যোগফলটি রয়েছে, উপাদানগুলির গণনা নয় (আরও সঠিক এন = বাইট / শব্দের আকার হতে হবে)
ব্যবহারকারী 1416420

@ ব্যবহারকারী 1416420 আমি ভুল হতে পারি, তবে এটি কেন? কি হবে যদি এটি কিছু অন্য ধরনের (যেমন। একটি সংগ্রহ bool, intইত্যাদি)? আপনার সংগ্রহের প্রতিটি স্ট্রিংয়ের একটি অনুলিপি তৈরি করতে হবে না। আপনি কেবল তাদের নতুন তালিকায় যুক্ত করুন।
অস্কার মেডেরোস

তবুও নতুন মেমরি বরাদ্দ এবং বাইটস অনুলিপি করার বিষয়টি বিবেচনা করে না যা এই পদ্ধতিটি হারাচ্ছে। । নেট এ 4 টি বাইটও দখল করবে। প্রকৃতপক্ষে .NET- তে কোনও সামগ্রীর প্রতিটি রেফারেন্স কমপক্ষে 8 বাইট দীর্ঘ, তাই এটি বেশ ধীর। প্রথম 4 বাইট টাইপ টেবিলের দিকে নির্দেশ করে এবং দ্বিতীয় 4 বাইট মান বা মেমরির অবস্থানের দিকে নির্দেশ করে যেখানে মানটি পাওয়া যায়
ব্যবহারকারী 1416420

3

ফাইল তালিকা পুনরুদ্ধারের কর্মক্ষমতা বিবেচনা করা, ToList()নগণ্য। তবে সত্যিই অন্যান্য পরিস্থিতিতে নয়। এটি আপনি কোথায় এটি ব্যবহার করছেন তা নির্ভর করে।

  • কোনও অ্যারে, তালিকা বা অন্য সংগ্রহের দিকে কল করার সময় আপনি সংগ্রহ হিসাবে একটি অনুলিপি তৈরি করেন List<T>। এখানে কর্মক্ষমতা তালিকা আকারের উপর নির্ভর করে। সত্যই প্রয়োজনে আপনার এটি করা উচিত।

    আপনার উদাহরণস্বরূপ, আপনি এটি অ্যারেতে কল করেছেন। এটি অ্যারের উপরে পুনরাবৃত্তি করে এবং আইটেমগুলি একে একে নতুন তৈরি তালিকায় যুক্ত করে। সুতরাং কর্মক্ষমতা প্রভাব ফাইলের সংখ্যার উপর নির্ভর করে।

  • যখন কোনটিতে কল করার সময় IEnumerable<T>আপনি (সাধারণত একটি ক্যোয়ারী) বস্তুতে পরিণত হন IEnumerable<T>


2

টোললিস্ট একটি নতুন তালিকা তৈরি করবে এবং নতুন উত্স থেকে নতুন তৈরি তালিকায় উপাদানগুলি অনুলিপি করবে তাই মূল উত্স থেকে উপাদানগুলি অনুলিপি করা কেবল উত্সের আকারের উপর নির্ভর করে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.