ঠিক আছে, এই জিনিসটি বিশ্রামে রাখার জন্য, আমি বেশ কয়েকটি পরিস্থিতি চালানোর জন্য এবং ফলাফলের কিছু দৃশ্যধারণের জন্য একটি পরীক্ষা অ্যাপ তৈরি করেছি। পরীক্ষাগুলি কীভাবে করা হয় তা এখানে:
- বিভিন্ন সংগ্রহের আকারের কয়েকটি চেষ্টা করা হয়েছে: একশ, এক হাজার এবং এক লক্ষ হাজার এন্ট্রি।
- ব্যবহৃত কীগুলি কোনও শ্রেণীর উদাহরণ যা আইডি দ্বারা স্বতন্ত্রভাবে চিহ্নিত করা হয়। প্রতিটি পরীক্ষায় আইডি হিসাবে বর্ধমান পূর্ণসংখ্যার সাথে অনন্য কী ব্যবহার করা হয়।
equals
পদ্ধতি শুধুমাত্র আইডি ব্যবহার তাই কোনও কী ম্যাপিং অন্য এক মুছে ফেলা হয়।
- কীগুলি একটি হ্যাশ কোড পায় যা কিছু প্রিসেট সংখ্যার বিপরীতে তাদের আইডি মডিউল বাকি থাকে। আমরা সেই নম্বরটিকে হ্যাশ সীমাতে কল করব । এটি আমাকে প্রত্যাশিত হ্যাশ সংঘর্ষের সংখ্যা নিয়ন্ত্রণ করতে দেয়। উদাহরণস্বরূপ, যদি আমাদের সংগ্রহের আকার 100 হয়, তবে আমাদের 0 থেকে 99 টি আইডি সহ কীগুলি থাকবে the হ্যাশের সীমা যদি 50 হয় তবে কী 0-তে একই 50 টির মতো হ্যাশ কোড থাকবে, 1 টিতে 51 এর সমান হ্যাশ কোড থাকবে other সীমা
- সংগ্রহের আকার এবং হ্যাশ সীমাটির প্রতিটি সংমিশ্রণের জন্য, আমি হ্যাশ মানচিত্রগুলি বিভিন্ন সেটিংসের সাথে ইনিশিয়াল করে ব্যবহার করে পরীক্ষা চালিয়েছি। এই সেটিংসগুলি লোড ফ্যাক্টর এবং একটি প্রাথমিক ক্ষমতা যা সংগ্রহের সেটিংয়ের ফ্যাক্টর হিসাবে প্রকাশ করা হয়। উদাহরণস্বরূপ, 100 সংগ্রহের আকার এবং 1.25 এর প্রাথমিক ক্ষমতা ফ্যাক্টর সহ একটি পরীক্ষা 125 এর প্রাথমিক ক্ষমতা সহ একটি হ্যাশ মানচিত্রকে আরম্ভ করবে।
- প্রতিটি কি জন্য মান সহজভাবে একটি নতুন
Object
।
- প্রতিটি পরীক্ষার ফলাফল একটি ফলাফল শ্রেণীর উদাহরণে আবশ্যক। সমস্ত পরীক্ষার শেষে, ফলাফলগুলি খারাপতম সামগ্রিক পারফরম্যান্স থেকে সেরা পর্যন্ত অর্ডার করা হয়।
- পুটস এবং গেনসের জন্য গড় সময় প্রতি 10 পুট / গেস গণনা করা হয়।
- সমস্ত পরীক্ষার সংমিশ্রণগুলি একবার জেআইটি সংকলনের প্রভাব দূর করতে পরিচালিত হয়। এর পরে, পরীক্ষাগুলি প্রকৃত ফলাফলের জন্য পরিচালিত হয়।
এখানে ক্লাস:
package hashmaptest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
public class HashMapTest {
private static final List<Result> results = new ArrayList<Result>();
public static void main(String[] args) throws IOException {
final int[][] sampleSizesAndHashLimits = new int[][] {
{100, 50, 90, 100},
{1000, 500, 900, 990, 1000},
{100000, 10000, 90000, 99000, 100000}
};
final double[] initialCapacityFactors = new double[] {0.5, 0.75, 1.0, 1.25, 1.5, 2.0};
final float[] loadFactors = new float[] {0.5f, 0.75f, 1.0f, 1.25f};
for(int[] sizeAndLimits : sampleSizesAndHashLimits) {
int size = sizeAndLimits[0];
for(int i = 1; i < sizeAndLimits.length; ++i) {
int limit = sizeAndLimits[i];
for(double initCapacityFactor : initialCapacityFactors) {
for(float loadFactor : loadFactors) {
runTest(limit, size, initCapacityFactor, loadFactor);
}
}
}
}
results.clear();
for(int[] sizeAndLimits : sampleSizesAndHashLimits) {
int size = sizeAndLimits[0];
for(int i = 1; i < sizeAndLimits.length; ++i) {
int limit = sizeAndLimits[i];
for(double initCapacityFactor : initialCapacityFactors) {
for(float loadFactor : loadFactors) {
runTest(limit, size, initCapacityFactor, loadFactor);
}
}
}
}
Collections.sort(results);
for(final Result result : results) {
result.printSummary();
}
}
private static void runTest(final int hashLimit, final int sampleSize,
final double initCapacityFactor, final float loadFactor) {
final int initialCapacity = (int)(sampleSize * initCapacityFactor);
System.out.println("Running test for a sample collection of size " + sampleSize
+ ", an initial capacity of " + initialCapacity + ", a load factor of "
+ loadFactor + " and keys with a hash code limited to " + hashLimit);
System.out.println("====================");
double hashOverload = (((double)sampleSize/hashLimit) - 1.0) * 100.0;
System.out.println("Hash code overload: " + hashOverload + "%");
final List<Key> keys = generateSamples(hashLimit, sampleSize);
final List<Object> values = generateValues(sampleSize);
final HashMap<Key, Object> map = new HashMap<Key, Object>(initialCapacity, loadFactor);
final long startPut = System.nanoTime();
for(int i = 0; i < sampleSize; ++i) {
map.put(keys.get(i), values.get(i));
}
final long endPut = System.nanoTime();
final long putTime = endPut - startPut;
final long averagePutTime = putTime/(sampleSize/10);
System.out.println("Time to map all keys to their values: " + putTime + " ns");
System.out.println("Average put time per 10 entries: " + averagePutTime + " ns");
final long startGet = System.nanoTime();
for(int i = 0; i < sampleSize; ++i) {
map.get(keys.get(i));
}
final long endGet = System.nanoTime();
final long getTime = endGet - startGet;
final long averageGetTime = getTime/(sampleSize/10);
System.out.println("Time to get the value for every key: " + getTime + " ns");
System.out.println("Average get time per 10 entries: " + averageGetTime + " ns");
System.out.println("");
final Result result =
new Result(sampleSize, initialCapacity, loadFactor, hashOverload, averagePutTime, averageGetTime, hashLimit);
results.add(result);
System.gc();
try {
Thread.sleep(200);
} catch(final InterruptedException e) {}
}
private static List<Key> generateSamples(final int hashLimit, final int sampleSize) {
final ArrayList<Key> result = new ArrayList<Key>(sampleSize);
for(int i = 0; i < sampleSize; ++i) {
result.add(new Key(i, hashLimit));
}
return result;
}
private static List<Object> generateValues(final int sampleSize) {
final ArrayList<Object> result = new ArrayList<Object>(sampleSize);
for(int i = 0; i < sampleSize; ++i) {
result.add(new Object());
}
return result;
}
private static class Key {
private final int hashCode;
private final int id;
Key(final int id, final int hashLimit) {
this.id = id;
this.hashCode = id % hashLimit;
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public boolean equals(final Object o) {
return ((Key)o).id == this.id;
}
}
static class Result implements Comparable<Result> {
final int sampleSize;
final int initialCapacity;
final float loadFactor;
final double hashOverloadPercentage;
final long averagePutTime;
final long averageGetTime;
final int hashLimit;
Result(final int sampleSize, final int initialCapacity, final float loadFactor,
final double hashOverloadPercentage, final long averagePutTime,
final long averageGetTime, final int hashLimit) {
this.sampleSize = sampleSize;
this.initialCapacity = initialCapacity;
this.loadFactor = loadFactor;
this.hashOverloadPercentage = hashOverloadPercentage;
this.averagePutTime = averagePutTime;
this.averageGetTime = averageGetTime;
this.hashLimit = hashLimit;
}
@Override
public int compareTo(final Result o) {
final long putDiff = o.averagePutTime - this.averagePutTime;
final long getDiff = o.averageGetTime - this.averageGetTime;
return (int)(putDiff + getDiff);
}
void printSummary() {
System.out.println("" + averagePutTime + " ns per 10 puts, "
+ averageGetTime + " ns per 10 gets, for a load factor of "
+ loadFactor + ", initial capacity of " + initialCapacity
+ " for " + sampleSize + " mappings and " + hashOverloadPercentage
+ "% hash code overload.");
}
}
}
এটি চালাতে কিছু সময় লাগতে পারে। ফলাফলগুলি স্ট্যান্ডার্ড আউটতে মুদ্রিত হয়। আপনি খেয়াল করতে পারেন আমি একটি লাইন মন্তব্য করেছি। এই লাইনটি একটি ভিজ্যুয়ালাইজারকে কল করে যা ফলাফলগুলির ভিজ্যুয়াল উপস্থাপনাগুলিকে পিএনজি ফাইলগুলিতে আউটপুট করে। এর জন্য ক্লাসটি নীচে দেওয়া হল। আপনি যদি এটি চালাতে চান তবে উপরের কোডে যথাযথ লাইনটি আপত্তি করুন সতর্কতা অবলম্বন করুন: ভিজ্যুয়ালাইজার শ্রেণি ধরে নেয় যে আপনি উইন্ডোজটিতে চলছে এবং সি: \ টেম্পে ফোল্ডার এবং ফাইলগুলি তৈরি করবে। অন্য প্ল্যাটফর্মে চলার সময় এটিকে সামঞ্জস্য করুন।
package hashmaptest;
import hashmaptest.HashMapTest.Result;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.imageio.ImageIO;
public class ResultVisualizer {
private static final Map<Integer, Map<Integer, Set<Result>>> sampleSizeToHashLimit =
new HashMap<Integer, Map<Integer, Set<Result>>>();
private static final DecimalFormat df = new DecimalFormat("0.00");
static void visualizeResults(final List<Result> results) throws IOException {
final File tempFolder = new File("C:\\temp");
final File baseFolder = makeFolder(tempFolder, "hashmap_tests");
long bestPutTime = -1L;
long worstPutTime = 0L;
long bestGetTime = -1L;
long worstGetTime = 0L;
for(final Result result : results) {
final Integer sampleSize = result.sampleSize;
final Integer hashLimit = result.hashLimit;
final long putTime = result.averagePutTime;
final long getTime = result.averageGetTime;
if(bestPutTime == -1L || putTime < bestPutTime)
bestPutTime = putTime;
if(bestGetTime <= -1.0f || getTime < bestGetTime)
bestGetTime = getTime;
if(putTime > worstPutTime)
worstPutTime = putTime;
if(getTime > worstGetTime)
worstGetTime = getTime;
Map<Integer, Set<Result>> hashLimitToResults =
sampleSizeToHashLimit.get(sampleSize);
if(hashLimitToResults == null) {
hashLimitToResults = new HashMap<Integer, Set<Result>>();
sampleSizeToHashLimit.put(sampleSize, hashLimitToResults);
}
Set<Result> resultSet = hashLimitToResults.get(hashLimit);
if(resultSet == null) {
resultSet = new HashSet<Result>();
hashLimitToResults.put(hashLimit, resultSet);
}
resultSet.add(result);
}
System.out.println("Best average put time: " + bestPutTime + " ns");
System.out.println("Best average get time: " + bestGetTime + " ns");
System.out.println("Worst average put time: " + worstPutTime + " ns");
System.out.println("Worst average get time: " + worstGetTime + " ns");
for(final Integer sampleSize : sampleSizeToHashLimit.keySet()) {
final File sizeFolder = makeFolder(baseFolder, "sample_size_" + sampleSize);
final Map<Integer, Set<Result>> hashLimitToResults =
sampleSizeToHashLimit.get(sampleSize);
for(final Integer hashLimit : hashLimitToResults.keySet()) {
final File limitFolder = makeFolder(sizeFolder, "hash_limit_" + hashLimit);
final Set<Result> resultSet = hashLimitToResults.get(hashLimit);
final Set<Float> loadFactorSet = new HashSet<Float>();
final Set<Integer> initialCapacitySet = new HashSet<Integer>();
for(final Result result : resultSet) {
loadFactorSet.add(result.loadFactor);
initialCapacitySet.add(result.initialCapacity);
}
final List<Float> loadFactors = new ArrayList<Float>(loadFactorSet);
final List<Integer> initialCapacities = new ArrayList<Integer>(initialCapacitySet);
Collections.sort(loadFactors);
Collections.sort(initialCapacities);
final BufferedImage putImage =
renderMap(resultSet, loadFactors, initialCapacities, worstPutTime, bestPutTime, false);
final BufferedImage getImage =
renderMap(resultSet, loadFactors, initialCapacities, worstGetTime, bestGetTime, true);
final String putFileName = "size_" + sampleSize + "_hlimit_" + hashLimit + "_puts.png";
final String getFileName = "size_" + sampleSize + "_hlimit_" + hashLimit + "_gets.png";
writeImage(putImage, limitFolder, putFileName);
writeImage(getImage, limitFolder, getFileName);
}
}
}
private static File makeFolder(final File parent, final String folder) throws IOException {
final File child = new File(parent, folder);
if(!child.exists())
child.mkdir();
return child;
}
private static BufferedImage renderMap(final Set<Result> results, final List<Float> loadFactors,
final List<Integer> initialCapacities, final float worst, final float best,
final boolean get) {
final Color[][] map = new Color[initialCapacities.size()][loadFactors.size()];
for(final Result result : results) {
final int x = initialCapacities.indexOf(result.initialCapacity);
final int y = loadFactors.indexOf(result.loadFactor);
final float time = get ? result.averageGetTime : result.averagePutTime;
final float score = (time - best)/(worst - best);
final Color c = new Color(score, 1.0f - score, 0.0f);
map[x][y] = c;
}
final int imageWidth = initialCapacities.size() * 40 + 50;
final int imageHeight = loadFactors.size() * 40 + 50;
final BufferedImage image =
new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_3BYTE_BGR);
final Graphics2D g = image.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, imageWidth, imageHeight);
for(int x = 0; x < map.length; ++x) {
for(int y = 0; y < map[x].length; ++y) {
g.setColor(map[x][y]);
g.fillRect(50 + x*40, imageHeight - 50 - (y+1)*40, 40, 40);
g.setColor(Color.BLACK);
g.drawLine(25, imageHeight - 50 - (y+1)*40, 50, imageHeight - 50 - (y+1)*40);
final Float loadFactor = loadFactors.get(y);
g.drawString(df.format(loadFactor), 10, imageHeight - 65 - (y)*40);
}
g.setColor(Color.BLACK);
g.drawLine(50 + (x+1)*40, imageHeight - 50, 50 + (x+1)*40, imageHeight - 15);
final int initialCapacity = initialCapacities.get(x);
g.drawString(((initialCapacity%1000 == 0) ? "" + (initialCapacity/1000) + "K" : "" + initialCapacity), 15 + (x+1)*40, imageHeight - 25);
}
g.drawLine(25, imageHeight - 50, imageWidth, imageHeight - 50);
g.drawLine(50, 0, 50, imageHeight - 25);
g.dispose();
return image;
}
private static void writeImage(final BufferedImage image, final File folder,
final String filename) throws IOException {
final File imageFile = new File(folder, filename);
ImageIO.write(image, "png", imageFile);
}
}
ভিজ্যুয়ালাইজড আউটপুট নিম্নরূপ:
- পরীক্ষাগুলি সংগ্রহের আকারের দ্বারা প্রথমে ভাগ করা হয়, তারপরে হ্যাশ সীমা দ্বারা।
- প্রতিটি পরীক্ষার জন্য, গড় পুট সময় (প্রতি 10 পুটস) এবং গড় পেতে সময় (প্রতি 10 পায়) সম্পর্কিত একটি আউটপুট চিত্র থাকে। চিত্রগুলি দ্বিমাত্রিক "তাপের মানচিত্র" যা প্রাথমিক ক্ষমতা এবং লোড ফ্যাক্টরের সংমিশ্রণে একটি রঙ দেখায়।
- চিত্রগুলিতে বর্ণগুলি স্যাচুরেটেড সবুজ থেকে শুরু করে স্যাচুরেটেড লাল থেকে শুরু করে সেরা থেকে সবচেয়ে খারাপ পরিণতি পর্যন্ত স্বাভাবিকের স্কেলে গড় সময়ের ভিত্তিতে থাকে। অন্য কথায়, সেরা সময়টি পুরোপুরি সবুজ হবে, যখন সবচেয়ে খারাপ সময়টি পুরো লাল হবে। দুটি পৃথক সময় পরিমাপের একই রঙ হওয়া উচিত নয়।
- রঙের মানচিত্রগুলি পুট এবং পাওয়ার জন্য পৃথকভাবে গণনা করা হয় তবে স্ব স্ব বিভাগগুলির জন্য সমস্ত পরীক্ষা অন্তর্ভুক্ত করে।
- ভিজ্যুয়ালাইজেশনগুলি তাদের x অক্ষের প্রাথমিক ক্ষমতা এবং y অক্ষের উপর লোড ফ্যাক্টরটি দেখায়।
আরও অগ্রগতি ছাড়াই, আসুন ফলাফলগুলি একবার দেখুন। আমি puts জন্য ফলাফল দিয়ে শুরু করব।
ফলাফল রাখুন
সংগ্রহের আকার: 100. হ্যাশ সীমা: 50. এর অর্থ প্রতিটি হ্যাশ কোডটি দু'বার হওয়া উচিত এবং প্রতিটি অন্যান্য কী হ্যাশ মানচিত্রে সংঘর্ষিত হয়।
ঠিক আছে, এটি খুব ভাল শুরু হয় না। আমরা দেখতে পাই যে সংগ্রহের আকারের 25% উপরে 1% এর লোড ফ্যাক্টর সহ প্রাথমিক ক্ষমতার জন্য একটি বড় হটস্পট রয়েছে The নীচের বাম কোণটি খুব ভাল সম্পাদন করে না।
সংগ্রহের আকার: 100. হ্যাশ সীমা: 90. দশটি কীতে একটিতে সদৃশ হ্যাশ কোড রয়েছে।
এটি একটি সামান্য আরও বাস্তব চিত্র, সঠিক হ্যাশ ফাংশন না থাকলেও 10% ওভারলোড but হটস্পট চলে গেছে, তবে কম লোড ফ্যাক্টরের সাথে স্বল্প প্রাথমিক ক্ষমতার সংমিশ্রণটি সম্ভবত কাজ করে না।
সংগ্রহের আকার: 100. হ্যাশ সীমা: 100. প্রতিটি কী এর নিজস্ব অনন্য হ্যাশ কোড হিসাবে। পর্যাপ্ত বালতি থাকলে কোনও সংঘর্ষের প্রত্যাশা নেই।
1 এর লোড ফ্যাক্টর সহ 100 এর প্রাথমিক ক্ষমতাটি সূক্ষ্ম বলে মনে হচ্ছে। আশ্চর্যজনকভাবে, লোড ফ্যাক্টর সহ উচ্চতর প্রাথমিক ক্ষমতা অগত্যা ভাল নয়।
সংগ্রহের আকার: 1000. হ্যাশ সীমা: 500. এটি 1000 টি এন্ট্রি সহ এখানে আরও গুরুতর হয়ে উঠছে। ঠিক প্রথম পরীক্ষার মতোই এখানে 2 থেকে 1 এর একটি হ্যাশ ওভারলোড রয়েছে।
নীচের বাম কোণটি এখনও ভাল করছে না। তবে নিম্ন প্রাথমিক গণনা / উচ্চ লোড ফ্যাক্টর এবং উচ্চতর প্রাথমিক গণনা / লো লোড ফ্যাক্টরের কম্বোর মধ্যে একটি প্রতিসাম্য বলে মনে হচ্ছে।
সংগ্রহের আকার: 1000. হ্যাশ সীমা: 900. এর অর্থ দশটি হ্যাশ কোডের মধ্যে একটি হ'ল দু'বার হবে। সংঘর্ষের বিষয়ে যুক্তিসঙ্গত দৃশ্য।
প্রাথমিক ক্ষমতার সম্ভাব্য কম্বোতে খুব মজার কিছু চলছে যা 1 এর উপরে লোড ফ্যাক্টরের সাথে খুব কম, যা পাল্টা স্বজ্ঞাত int অন্যথায়, এখনও যথেষ্ট প্রতিসম।
সংগ্রহের আকার: 1000. হ্যাশ সীমা: 990. কিছু সংঘর্ষ, তবে কয়েকটি। এই ক্ষেত্রে যথেষ্ট বাস্তববাদী।
আমরা এখানে একটি দুর্দান্ত প্রতিসাম্য পেয়েছি। নীচের বাম কোণটি এখনও সাব-অনুকূল, তবে কম্বোস 1000 ডিআইডি ক্ষমতা / 1.0 লোড ফ্যাক্টর বনাম 1250 আরডি ক্ষমতা / 0.75 লোড ফ্যাক্টর একই স্তরে রয়েছে।
সংগ্রহের আকার: 1000. হ্যাশ সীমা: 1000. কোনও সদৃশ হ্যাশ কোড নেই, তবে এখন 1000 এর নমুনা আকারের।
এখানে খুব বেশি কিছু বলা যায় না। 0.75 লোড ফ্যাক্টরের সাথে উচ্চতর প্রাথমিক ক্ষমতার সংমিশ্রণটি 1 এর লোড ফ্যাক্টরের সাথে 1000 প্রাথমিক ক্ষমতার সংমিশ্রণটিকে সামান্য ছাড়িয়ে গেছে বলে মনে হচ্ছে।
সংগ্রহের আকার: 100_000। হ্যাশ সীমা: 10_000। ঠিক আছে, এখন প্রতি সিরিয় একশো হাজার এবং হ্যাশ কোডের নকলের নমুনা আকারের সাথে এটি গুরুতর হয়ে উঠছে।
হায়! আমি মনে করি আমরা আমাদের নিম্ন বর্ণালীটি পেয়েছি। 1 এর লোড ফ্যাক্টর সহ সঠিকভাবে সংগ্রহের আকারের একটি ইআরসি ক্ষমতা এখানে খুব ভাল করছে তবে এটি সমস্ত দোকান জুড়েই রয়েছে।
সংগ্রহের আকার: 100_000। হ্যাশ সীমা: 90_000। পূর্ববর্তী পরীক্ষার চেয়ে কিছুটা বাস্তবসম্মত, এখানে আমরা হ্যাশ কোডগুলিতে একটি 10% ওভারলোড পেয়েছি।
নীচের বাম কোণটি এখনও অনাকাঙ্ক্ষিত। উচ্চতর প্রাথমিক ক্ষমতা সর্বোত্তম কাজ করে।
সংগ্রহের আকার: 100_000। হ্যাশ সীমা: 99_000। ভাল দৃশ্য, এটি। 1% হ্যাশ কোড ওভারলোড সহ একটি বৃহত সংগ্রহ।
1 টির লোড ফ্যাক্টর সহ ডিআইডি ক্ষমতা হিসাবে সঠিক সংগ্রহের আকারটি এখানে জিততে পারে! যদিও সামান্য বৃহত্তর init সক্ষমতা বেশ ভালভাবে কাজ করে work
সংগ্রহের আকার: 100_000। হ্যাশ সীমা: 100_000। বড় এক. একটি নিখুঁত হ্যাশ ফাংশন সহ বৃহত্তম সংগ্রহ।
কিছু বিস্ময়কর জিনিস এখানে। 1 জয়ের লোড ফ্যাক্টরে 50% অতিরিক্ত কক্ষ সহ প্রাথমিক ক্ষমতা।
ঠিক আছে, এটা পুটদের জন্য। এখন, আমরা কীগুলি পরীক্ষা করব। মনে রাখবেন, নীচের মানচিত্রগুলি সর্বোত্তম / খারাপ সময়গুলির সাথে সম্পর্কিত, পুট সময়গুলিকে আর বিবেচনায় নেওয়া হয় না।
ফলাফল পান
সংগ্রহের আকার: 100. হ্যাশ সীমা: 50. এর অর্থ প্রতিটি হ্যাশ কোডটি দু'বার হওয়া উচিত এবং প্রতিটি অন্যান্য কী হ্যাশ মানচিত্রে সংঘর্ষে প্রত্যাশিত।
এহ ... কি?
সংগ্রহের আকার: 100. হ্যাশ সীমা: 90. দশটি কীতে একটিতে সদৃশ হ্যাশ কোড রয়েছে।
ওহে নেলি! এটিই সম্ভবত প্রশ্নকের প্রশ্নের সাথে সম্পর্কিত হতে পারে এবং দৃশ্যত 1 এর লোড ফ্যাক্টরের সাথে 100 এর প্রাথমিক ক্ষমতা এখানে সবচেয়ে খারাপ জিনিসগুলির মধ্যে একটি! আমি শপথ করছি আমি এই জাল না।
সংগ্রহের আকার: 100. হ্যাশ সীমা: 100. প্রতিটি কী এর নিজস্ব অনন্য হ্যাশ কোড হিসাবে। কোনও সংঘর্ষ আশা করা যায় না।
এটিকে কিছুটা বেশি শান্ত লাগছে। বোর্ড জুড়ে প্রায় একই ফলাফল।
সংগ্রহের আকার: 1000. হ্যাশ সীমা: 500. ঠিক প্রথম পরীক্ষার মতোই 2 থেকে 1 এর হ্যাশ ওভারলোড রয়েছে তবে এখন আরও অনেক এন্ট্রি রয়েছে।
দেখে মনে হচ্ছে যে কোনও সেটিংস এখানে একটি ভাল ফলাফল দেবে।
সংগ্রহের আকার: 1000. হ্যাশ সীমা: 900. এর অর্থ দশটি হ্যাশ কোডের মধ্যে একটি হ'ল দু'বার হবে। সংঘর্ষের বিষয়ে যুক্তিসঙ্গত দৃশ্য।
এবং ঠিক এই সেটআপটির জন্য রাখার মতো, আমরা একটি অদ্ভুত স্পটে একটি অসাধারণতা পেয়েছি।
সংগ্রহের আকার: 1000. হ্যাশ সীমা: 990. কিছু সংঘর্ষ, তবে কয়েকটি। এই ক্ষেত্রে যথেষ্ট বাস্তববাদী।
সর্বত্র শালীন কর্মক্ষমতা, কম লোড ফ্যাক্টরের সাথে উচ্চ প্রাথমিক ক্ষমতার সংমিশ্রনের জন্য সংরক্ষণ করুন। আমি পুটের জন্য এটি আশা করবো, যেহেতু দুটি হ্যাশ মানচিত্রের আকারের প্রত্যাশা করা যেতে পারে। তবে কেন পেল?
সংগ্রহের আকার: 1000. হ্যাশ সীমা: 1000. কোনও সদৃশ হ্যাশ কোড নেই, তবে এখন 1000 এর নমুনা আকারের।
একটি সম্পূর্ণ অনিচ্ছাকৃত দৃশ্য। এটি যাই হোক না কেন কাজ করে বলে মনে হচ্ছে।
সংগ্রহের আকার: 100_000। হ্যাশ সীমা: 10_000। পুরো 100 টি হ্যাশ কোডের ওভারল্যাপের সাথে আবার 100 কে।
এটি দেখতে সুন্দর দেখাচ্ছে না, যদিও খারাপ দাগগুলি খুব স্থানীয় রয়েছে। এখানে পারফরম্যান্স বেশিরভাগ ক্ষেত্রে সেটিংসের মধ্যে একটি নির্দিষ্ট সিনেরির উপর নির্ভর করে।
সংগ্রহের আকার: 100_000। হ্যাশ সীমা: 90_000। পূর্ববর্তী পরীক্ষার চেয়ে কিছুটা বাস্তবসম্মত, এখানে আমরা হ্যাশ কোডগুলিতে একটি 10% ওভারলোড পেয়েছি।
অনেকগুলি বৈকল্পিকতা, যদিও আপনি স্ক্রিন্ট করলে আপনি উপরের ডানদিকে কোণায় নির্দেশিত একটি তীর দেখতে পাবেন।
সংগ্রহের আকার: 100_000। হ্যাশ সীমা: 99_000। ভাল দৃশ্য, এটি। 1% হ্যাশ কোড ওভারলোড সহ একটি বৃহত সংগ্রহ।
খুব বিশৃঙ্খল। এখানে অনেক কাঠামো খুঁজে পাওয়া শক্ত।
সংগ্রহের আকার: 100_000। হ্যাশ সীমা: 100_000। বড় এক. একটি নিখুঁত হ্যাশ ফাংশন সহ বৃহত্তম সংগ্রহ।
অন্য কেউ ভাবেন যে এটি আটারি গ্রাফিক্সের মতো দেখতে শুরু হচ্ছে? এটি সংগ্রহের সঠিক আকারের -25% বা + 50% এর প্রাথমিক ক্ষমতার পক্ষে বলে মনে হচ্ছে।
ঠিক আছে, এখনই সিদ্ধান্তের সময় ...
- পুট টাইম সম্পর্কিত: আপনি প্রাথমিক সক্ষমতা এড়াতে চান যা মানচিত্রের প্রবেশের প্রত্যাশিত সংখ্যার চেয়ে কম। যদি আগে থেকে কোনও সঠিক সংখ্যা জানা থাকে তবে number সংখ্যা বা কিছুটা উপরে এটি সেরা কাজ করে বলে মনে হচ্ছে। পূর্ববর্তী হ্যাশ মানচিত্রের আকারের কারণে উচ্চ লোড ফ্যাক্টরগুলি কম প্রাথমিক সামর্থ্যগুলি অফসেট করতে পারে। উচ্চতর প্রাথমিক ক্ষমতার জন্য, তাদের পক্ষে এতো কিছু মনে হয় না।
- প্রাপ্ত সময় সম্পর্কে: ফলাফলগুলি এখানে কিছুটা বিশৃঙ্খলাযুক্ত। উপসংহার করার মতো অনেক কিছুই নেই। মনে হচ্ছে কিছু হ্যাশ কোড ওভারল্যাপ, প্রাথমিক ক্ষমতা এবং লোড ফ্যাক্টরের মধ্যে সূক্ষ্ম অনুপাতের উপর খুব বেশি নির্ভর করে বলে মনে হচ্ছে কিছু খারাপ সেটআপ ভাল অভিনয় করছে এবং ভাল সেটআপগুলি দুর্দান্তভাবে পারফর্ম করছে।
- জাভা পারফরম্যান্স সম্পর্কে অনুমানের বিষয়টি যখন আসে তখন আমি স্পষ্টতই বাজে থাকি। সত্যটি হ'ল, যদি না আপনি নিজের সেটিংস প্রয়োগের ক্ষেত্রে পুরোপুরি টিউন করেন
HashMap
ফলাফলগুলি পুরো জায়গাতেই হবে। যদি এ থেকে দূরে নেওয়ার মতো কোনও জিনিস থাকে তবে তা হল যে 16 এর ডিফল্ট প্রাথমিক আকারটি ছোট ম্যাপ ছাড়া অন্য কোনও কিছুর জন্য কিছুটা বোবা, সুতরাং এমন কোন কনস্ট্রাক্টর ব্যবহার করুন যা আপনার আকারের ক্রম সম্পর্কে কোনও ধরণের ধারণা থাকলে প্রাথমিক আকার নির্ধারণ করে এটা হতে যাচ্ছে.
- আমরা এখানে ন্যানোসেকেন্ডে পরিমাপ করছি। 10 পুট প্রতি সেরা গড় সময় ছিল 1179 এনএস এবং আমার মেশিনে সবচেয়ে খারাপ 5105 এনএস। প্রতি 10 প্রতি গড় গড় গড় গড় ছিল 547 এনএস এবং সবচেয়ে খারাপ 3484 এনএস। এটি একটি ফ্যাক্টর 6 পার্থক্য হতে পারে, তবে আমরা একটি মিলিসেকেন্ডের চেয়ে কম কথা বলছি। মূল পোস্টারটি যা মনে রেখেছিল তার চেয়ে অনেক বড় আকারের সংগ্রহগুলিতে।
ঠিক আছে, এটা। আমি আশা করি যে আমার কোডটিতে এমন কিছু ভয়ঙ্কর নজরদারি নেই যা আমি এখানে পোস্ট করা সমস্ত কিছুকে অকার্যকর করে। এটি মজাদার হয়েছে, এবং আমি শিখেছি যে শেষ পর্যন্ত আপনি ক্ষুদ্রতর অপ্টিমাইজেশান থেকে অনেক পার্থক্য প্রত্যাশার চেয়ে তার কাজটি করার জন্য জাভার উপর নির্ভর করতে পারেন। এর অর্থ এই নয় যে কিছু জিনিস এড়ানো উচিত নয়, তবে আমরা প্রায়শই লুপগুলির জন্য দীর্ঘতর স্ট্রিংগুলি নির্মাণের কথা বলছি, ভুল ডেটাস্ট্রাকচার ব্যবহার করে ও (এন ^ 3) অ্যালগরিদম তৈরির বিষয়ে।