আমি অন্য দিনটি চালিয়ে গিয়েছিলাম এমন আরও একটি কৌশল এখানে রয়েছে:
Collections.nCopies(8, 1)
.stream()
.forEach(i -> System.out.println(i));
Collections.nCopiesকলের জন্য একটি সৃষ্টি Listধারণকারী nযাই হোক না কেন মান প্রদান কপি। এক্ষেত্রে এটি বাক্সযুক্ত Integerমান ১। অবশ্যই এটি nউপাদানগুলির সাথে তালিকাগুলি তৈরি করে না ; এটি একটি "ভার্চুয়ালাইজড" তালিকা তৈরি করে যা কেবলমাত্র মান এবং দৈর্ঘ্য ধারণ করে এবং getসীমার মধ্যে যে কোনও কল কেবল মানটি দেয়। nCopiesপদ্ধতি হয়েছে প্রায় যেহেতু সংগ্রহগুলি ফ্রেমওয়ার্ক JDK 1.2 উপায় ফিরে চালু করা হয়। অবশ্যই, জাভা এসই 8 এ এর ফলাফল থেকে একটি স্ট্রিম তৈরি করার ক্ষমতা যুক্ত করা হয়েছিল।
বড় চুক্তি, একই সংখ্যক লাইনের একই জিনিসটি করার আরেকটি উপায়।
তবে এই কৌশলটি দ্রুত IntStream.generateএবং IntStream.iterateপদ্ধতির চেয়ে দ্রুত এবং আশ্চর্যজনকভাবে এটি IntStream.rangeপদ্ধতির চেয়েও দ্রুত than
কারণ iterateএবং generateফলাফল সম্ভবত খুব অবাক হয় না। স্ট্রিমস ফ্রেমওয়ার্ক (প্রকৃতপক্ষে, এই স্ট্রিমগুলির জন্য স্প্লিটেটরগুলি) এই ধারণার উপর ভিত্তি করে তৈরি করা হয়েছে যে ল্যাম্বডাস প্রতিটিবারই সম্ভাব্যভাবে বিভিন্ন মান তৈরি করবে এবং তারা একটি সীমাহীন ফলাফল তৈরি করবে। এটি সমান্তরাল বিভাজন বিশেষ করে কঠিন করে তোলে। iterateপদ্ধতি কারণ প্রতিটি কলের আগের ফল প্রয়োজন এই ক্ষেত্রে জন্য সমস্যাযুক্ত। সুতরাং স্ট্রিমগুলি বারবার ধ্রুবক তৈরির জন্য খুব ভাল করে না generateএবং ব্যবহার করে iterateনা।
অপেক্ষাকৃত দুর্বল অভিনয় rangeবিস্ময়কর। এটিও ভার্চুয়ালাইজড, সুতরাং উপাদানগুলি মেমরির মধ্যে আসলে বিদ্যমান থাকে না এবং আকারটি সামনে জানা যায়। এটি দ্রুত এবং সহজেই সমান্তরাল স্প্লিট্রেটারের তৈরি করা উচিত। তবে এটি আশ্চর্যজনকভাবে খুব ভাল করেনি। সম্ভবত কারণটি হ'ল rangeপরিসরের প্রতিটি উপাদানটির জন্য একটি মান গণনা করতে হবে এবং তারপরে একটি ফাংশন কল করতে হবে। তবে এই ফাংশনটি কেবল তার ইনপুটটিকে উপেক্ষা করে একটি ধ্রুবককে ফিরিয়ে দেয়, তাই আমি আশ্চর্য হয়েছি যে এটি ইনলাইনড এবং হত্যা করা হয়নি।
Collections.nCopiesকৌশল যেহেতু কোন আদিম বিশেষায়িত হয়, যাতে মান হ্যান্ডেল করার জন্য আনবক্সিং / বক্সিং কি আছে List। যেহেতু প্রতিবার মান একই হয় তাই এটি মূলত একবারে বক্স করা হয় এবং সেই বাক্সটি সমস্ত nঅনুলিপি দ্বারা ভাগ করা হয় । আমি সন্দেহ করি বক্সিং / আনবক্সিং উচ্চতর অনুকূলিত, এমনকি স্বতঃস্ফূর্ত এবং এটি ভালভাবে ইনলাইন করা যেতে পারে।
কোডটি এখানে:
public static final int LIMIT = 500_000_000;
public static final long VALUE = 3L;
public long range() {
return
LongStream.range(0, LIMIT)
.parallel()
.map(i -> VALUE)
.map(i -> i % 73 % 13)
.sum();
}
public long ncopies() {
return
Collections.nCopies(LIMIT, VALUE)
.parallelStream()
.mapToLong(i -> i)
.map(i -> i % 73 % 13)
.sum();
}
এবং এখানে জেএমএইচ ফলাফল রয়েছে: (2.8GHz কোর 2 ডুও)
Benchmark Mode Samples Mean Mean error Units
c.s.q.SO18532488.ncopies thrpt 5 7.547 2.904 ops/s
c.s.q.SO18532488.range thrpt 5 0.317 0.064 ops/s
এনসিপিগুলি সংস্করণে যথেষ্ট পরিমাণে বৈকল্পিক রয়েছে তবে সামগ্রিকভাবে এটি পরিসীমা সংস্করণের তুলনায় আরামদায়কভাবে 20x দ্রুত বলে মনে হচ্ছে। (যদিও আমি বিশ্বাস করতে বেশ আগ্রহী যে আমি কিছু ভুল করেছি।)
nCopiesকৌশলটি কতটা ভাল কাজ করে তা নিয়ে আমি অবাক । অভ্যন্তরীণভাবে এটি খুব বেশি বিশেষ করে না, ভার্চুয়ালাইজড তালিকার প্রবাহটি কেবল ব্যবহার করে প্রয়োগ করা হচ্ছে IntStream.range! আমি প্রত্যাশা করেছি যে এটি দ্রুত যাওয়ার জন্য একটি বিশেষায়িত স্প্লিটেটর তৈরি করা প্রয়োজন, তবে এটি ইতিমধ্যে বেশ ভাল বলে মনে হচ্ছে।