প্রদত্ত যে jdk1.6 এবং এর উপরের হাশম্যাপগুলি মাল্টি = থ্রেডিংয়ের ক্ষেত্রে সমস্যা সৃষ্টি করে, আমি কীভাবে আমার কোড ঠিক করব


83

আমি সম্প্রতি স্ট্যাকওভারফ্লোতে একটি প্রশ্ন উত্থাপন করেছি, তার পরে উত্তরটি পেয়েছি। প্রাথমিক প্রশ্নটি ছিল ম্বেটেক্স বা আবর্জনা সংগ্রহ ছাড়া অন্য কোন পদ্ধতিগুলি আমার বহু-থ্রেড জাভা প্রোগ্রামকে ধীর করতে পারে?

আমি আমার ভয়াবহতার মধ্যে আবিষ্কার করেছি যে হ্যাশম্যাপটি জেডিকে 1.6 এবং জেডিকে 1.7 এর মধ্যে পরিবর্তিত হয়েছে। এটিতে এখন কোডের একটি ব্লক রয়েছে যা হ্যাশম্যাপগুলি তৈরি করে সমস্ত থ্রেডকে সিঙ্ক্রোনাইজ করে।

JDK1.7.0_10 এ কোডের লাইন

 /**A randomizing value associated with this instance that is applied to hash code of  keys to make hash collisions harder to find.     */
transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);

যার কল শেষ হয়

 protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
        oldseed = seed.get();
        nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
 }    

অন্যান্য জেডিকে-তে অনুসন্ধান করে, আমি দেখতে পাচ্ছি যে এটি জেডিকে 1.5.0_22 বা জেডিকে 1.6.0_26 তে উপস্থিত নেই।

আমার কোডের উপর প্রভাব বিশাল। এটি এটিকে এমন করে তোলে যাতে আমি যখন threads৪ টি থ্রেডে রান করি তখন আমি 1 থ্রেডে চালিত হওয়ার চেয়ে কম পারফরম্যান্স পাই। একটি জেস্ট্যাক দেখায় যে বেশিরভাগ থ্রেডগুলি তাদের বেশিরভাগ সময় র্যান্ডমের সেই লুপটিতে কাটানোর জন্য ব্যয় করে।

সুতরাং আমার কাছে কিছু বিকল্প রয়েছে বলে মনে হচ্ছে:

  • আমার কোডটি পুনরায় লিখুন যাতে আমি হ্যাশম্যাপ ব্যবহার না করি তবে অনুরূপ কিছু ব্যবহার করি
  • আরটি.জার দিয়ে কোনওভাবে গোলমাল করুন এবং এর ভিতরে হ্যাশম্যাপটি প্রতিস্থাপন করুন
  • শ্রেণি পাথটি একরকম ছড়িয়ে পড়ে, সুতরাং প্রতিটি থ্রেড হ্যাশম্যাপের নিজস্ব সংস্করণ পায়

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

সাহায্যের জন্য ধন্যবাদ


4
এমন অনেক হ্যাশম্যাপ তৈরি করতে আপনার কী দরকার? আপনি কি করতে চেষ্টা করছেন?
fge

4
2 মন্তব্য: 1. সমকালীন হ্যাশম্যাপটি এটি ব্যবহার করে বলে মনে হচ্ছে না - এটি বিকল্প হতে পারে? ২. এই টুকরো কোডটি কেবল মানচিত্র তৈরি করতে বলা হয়। এর থেকে বোঝা যায় যে আপনি উচ্চ বিতর্ক হিসাবে কয়েক মিলিয়ন হ্যাশম্যাপ তৈরি করছেন - এটি কি সত্যিকারের একটি বাস্তব উত্পাদন বোঝা প্রতিফলিত করে?
assylias

4
প্রকৃতপক্ষে সমকালীন হ্যাশম্যাপটিও সেই পদ্ধতিটি ব্যবহার করে (ওরাকল জেডকে 1.7_10 তে) - তবে দৃশ্যত ওপেনজেডিके 7 তা করে না
assylias

4
@assylias আপনার এখানে সর্বশেষতম সংস্করণ পরীক্ষা করা উচিত । এই এক কোড যেমন একটি লাইন খেলা।
মার্কো টপলনিক

4
ভালভাবে AtomicLongকাজ করতে কম লেখার বিষয়ে স্টেভিস্কুরা বাজি রাখে। আপনার উচ্চ লেখার-ধারণা রয়েছে, তাই আপনার নিয়মিত এক্সক্লুসিভ লকিং দরকার। একটি সিঙ্ক্রোনাইজড HashMapকারখানা লিখুন এবং আপনি সম্ভবত একটি উন্নতি দেখতে পাবেন, যদি না আপনি এই থ্রেডগুলিতে কখনও না করেন তবে মানচিত্রের তাত্পর্য নয় is
মার্কো টপোলনিক

উত্তর:


56

আমি প্যাচটির মূল লেখক যা 7u6 এ উপস্থিত হয়েছিল, সিআর # 7118743: হ্যাশ-ভিত্তিক মানচিত্রের সাথে স্ট্রিংয়ের জন্য বিকল্প হ্যাশিং ‌

আমি সামনের দিকে স্বীকার করব যে হ্যাশসিডের সূচনাটি একটি বাধা হ'ল তবে আমরা সমস্যা হওয়ার আশা করি না কারণ হ্যাশ ম্যাপের উদাহরণ হিসাবে এটি একবারেই ঘটে। এই কোডটি বাধা হবার জন্য আপনাকে প্রতি সেকেন্ডে কয়েক হাজার বা হাজার হাজার হ্যাশ মানচিত্র তৈরি করতে হবে। এটি অবশ্যই সাধারণ নয়। আপনার অ্যাপ্লিকেশনটি এটি করার জন্য কোনও সত্য কারণ আছে ? এই হ্যাশ মানচিত্রগুলি আর কতক্ষণ লাইভ করে?

নির্বিশেষে, আমরা সম্ভবত এলোমেলো পরিবর্তে থ্রেডলোক্যালর্যান্ডমে স্যুইচিং এবং কম্ব্যাকের পরামর্শ অনুসারে সম্ভবত অলস সূচনাকরণের কিছু বৈকল্পিক অনুসন্ধান করব।

সম্পাদনা 3

বাডেনেকের জন্য একটি স্থিরতা জেডিকে 7 আপডেট পার্কিয়াল রেপোতে চাপানো হয়েছিল:

http://hg.openjdk.java.net/jdk7u/jdk7u-dev/jdk/rev/b03bbdef3a88

এই ফিক্সটি আসন্ন 7u40 রিলিজের অংশ হবে এবং এটি ইতিমধ্যে আইসডটিএ ২.৪ প্রকাশে উপলব্ধ।

7u40 এর চূড়ান্ত পরীক্ষার বিল্ডগুলি এখানে উপলভ্য:

https://jdk7.java.net/download.html

প্রতিক্রিয়া এখনও স্বাগত জানানো হয়। এটি ওপেনজেডিকে ডেভেলগুলি দেখেছেন তা নিশ্চিত হওয়ার জন্য এটি http://mail.openjdk.java.net/mailman/listinfo/core-libs-dev এ প্রেরণ করুন ।


4
এটি দেখার জন্য ধন্যবাদ। হ্যাঁ, এটির অনেকগুলি মানচিত্র তৈরি করার দরকার আছে: অ্যাপ্লিকেশনটি আসলে বেশ সহজ, তবে ১০০,০০০ লোক একে একে দ্বিতীয় বার আঘাত করতে পারে এবং এর অর্থ লক্ষ লক্ষ মানচিত্র খুব দ্রুত তৈরি করা যেতে পারে। আমি অবশ্যই এটি মানচিত্রগুলি ব্যবহার না করার জন্য এটি পুনরায় লিখতে পারি, তবে এটি খুব উচ্চ উন্নয়ন ব্যয়। আপাতত র্যান্ডম ক্ষেত্রটি হ্যাক করার জন্য প্রতিবিম্বটি ব্যবহার করার পরিকল্পনাটি ভাল দেখাচ্ছে
স্টেভ ইস্কুরা

4
মাইক, একটি নিকট-মেয়াদী ফিক্সের জন্য একটি পরামর্শ: থ্রেডলোক্যালর্যান্ডম (যা থ্রেড-লোকাল স্টোরেজ নিয়ে মেসেজ করে এমন অ্যাপ্লিকেশনগুলির নিজস্ব সমস্যাগুলি হবে) এর চেয়ে এটি আরও সহজ এবং সস্তায় (সময়, ঝুঁকি এবং পরীক্ষার নিরিখে) নাও হবে স্ট্রাইপ হ্যাশিং.হোল্ডার.এসইএএমএকেকে একটি অ্যারেতে (বলুন) <নাম কোর> এলোমেলো উদাহরণস্বরূপ এবং কলিং থ্রেডের আইডিটিকে% -index এ ব্যবহার করবেন? এটি তাত্ক্ষণিকভাবে কোনও লক্ষণীয় পার্শ্ব প্রতিক্রিয়া ছাড়াই প্রতি থ্রেড বিতর্ক উপশম করা উচিত (যদিও অপসারণ না করে)।
হোলার হাফস্টেট

10
@ এমডিগাইউ ওয়েব অ্যাপ্লিকেশনগুলিতে যেগুলির উচ্চ অনুরোধের হার রয়েছে এবং জেএসএন ব্যবহার করছে তারা প্রতি সেকেন্ডে প্রচুর সংখ্যক হ্যাশম্যাপ তৈরি করতে চলেছে, যেহেতু সমস্ত জেএসওএন লাইব্রেরি জেএসওন অবজেক্টগুলি ডিসস্রায়াল করতে হ্যাশম্যাপস বা লিংকডহ্যাশম্যাপ ব্যবহার করে না। জেএসএন ব্যবহার করে এমন ওয়েব অ্যাপ্লিকেশনগুলি ব্যাপক, এবং হ্যাশম্যাপগুলি তৈরি করা অ্যাপ্লিকেশন দ্বারা নিয়ন্ত্রিত হতে পারে না (তবে একটি লাইব্রেরি অ্যাপ্লিকেশন ব্যবহার করে), সুতরাং আমি বলব যে হ্যাশম্যাপগুলি তৈরি করার সময় কোনও বাধা নেই valid
sbordet

4
@ এমডুইগু সম্ভবত সিএএস কল করার আগে ওল্ডসিডটি একই কিনা তা পরীক্ষা করে দেখতে খুব সহজ সরল উপায় viation এই অপ্টিমাইজেশান (যা পরীক্ষা-পরীক্ষা এবং সেট বা টিটিএএস হিসাবে পরিচিত) অপ্রয়োজনীয় বলে মনে হতে পারে, তবে বিতর্ক হিসাবে এটি একটি গুরুত্বপূর্ণ পারফরম্যান্স প্রভাব ফেলতে পারে কারণ এটি ইতিমধ্যে জানে যদি এটি ব্যর্থ হয় তবে সিএএস চেষ্টা করা হয় নি। ব্যর্থ সিএএসের ক্যাশে লাইনের এমইএসআই স্থিতিটি অবৈধ হিসাবে নির্ধারণ করার দুর্ভাগ্যজনক পার্শ্ব-প্রতিক্রিয়া রয়েছে - সমস্ত পক্ষকে মেমরি থেকে মানটি পুনরুদ্ধার করতে হবে। অবশ্যই, বীজের হোলারের স্ট্রিপিং একটি দীর্ঘ দীর্ঘমেয়াদী ফিক্স, তবে তারপরেও টিটিএএস অপ্টিমাইজেশন ব্যবহার করা উচিত।
জেড ওয়েসলি-স্মিথ

4
আপনার অর্থ কি "শত বা হাজার" এর পরিবর্তে "কয়েক হাজার"? - বড় পার্থক্য
মাইকেল নেল

30

এটি "বাগ" এর মতো দেখতে আপনি চারপাশে কাজ করতে পারেন। এমন একটি সম্পত্তি রয়েছে যা নতুন "বিকল্প হ্যাশিং" বৈশিষ্ট্যটি অক্ষম করে:

jdk.map.althashing.threshold = -1

তবে বিকল্প হ্যাশিং অক্ষম করা যথেষ্ট নয় কারণ এটি এলোমেলো হ্যাশ বীজ উত্পাদন করে না (যদিও এটি সত্যই হওয়া উচিত)। সুতরাং আপনি যদি ওয়েল হ্যাশিং বন্ধ করে দেন, তবুও হ্যাশ মানচিত্রের ইনস্ট্যান্টেশনের সময় আপনার কাছে থ্রেড বিতর্ক রয়েছে।

এগুলির চারপাশে কাজ করার একটি বিশেষভাবে বাজে উপায় Randomহ্যাশ বীজ উত্পাদনের জন্য ব্যবহৃত হ'ল দৃষ্টান্তটি আপনার নিজের অ-সিঙ্ক্রোনাইজড সংস্করণ দিয়ে শক্তভাবে প্রতিস্থাপন করা :

// Create an instance of "Random" having no thread synchronization.
Random alwaysOne = new Random() {
    @Override
    protected int next(int bits) {
        return 1;
    }
};

// Get a handle to the static final field sun.misc.Hashing.Holder.SEED_MAKER
Class<?> clazz = Class.forName("sun.misc.Hashing$Holder");
Field field = clazz.getDeclaredField("SEED_MAKER");
field.setAccessible(true);

// Convince Java the field is not final.
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);

// Set our custom instance of Random into the field.
field.set(null, alwaysOne);

কেন এটি (সম্ভবত) নিরাপদ? কারণ Alt হ্যাশিং অক্ষম করা হয়েছে, এলোমেলোভাবে হ্যাশ বীজ উপেক্ষা করা হবে। সুতরাং আমাদের দৃষ্টান্তটি Randomএলোমেলো নয় তা কিছু যায় আসে না । সর্বদা এর মতো দুষ্টু হ্যাক সহ, সতর্কতার সাথে ব্যবহার করুন।

( স্থিতিশীল চূড়ান্ত ক্ষেত্রসমূহ সেট করে এমন কোডের জন্য https://stackoverflow.com/a/3301720/1899721 কে ধন্যবাদ )

--- সম্পাদনা ---

FWIW, নীচের পরিবর্তনটি হ্যাড HashMapহ্যাশিং অক্ষম করা হলে থ্রেডের বিতর্ককে দূর করবে:

-   transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
+   transient final int hashSeed;

...

         useAltHashing = sun.misc.VM.isBooted() &&
                 (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
+        hashSeed = useAltHashing ? sun.misc.Hashing.randomHashSeed(this) : 0;
         init();

অনুরূপ পদ্ধতির জন্য ব্যবহার করা যেতে পারে ConcurrentHashMap, ইত্যাদি।


4
ধন্যবাদ. এটি প্রকৃতপক্ষে একটি হ্যাক, তবে এটি অস্থায়ীভাবে সমস্যার সমাধান করে। এটি অবশ্যই উপরে বর্ণিত তালিকার যে কোনওটির চেয়ে ভাল সমাধান। দীর্ঘমেয়াদী যাইহোক, দ্রুত হ্যাশম্যাপের সাহায্যে আমার কিছু করতে হবে। এটি পুরানো রিসোর্সবাণ্ডল ক্যাশে পরিষ্কার না হওয়ার সমাধানের বিষয়টি মনে করিয়ে দেয়। কোডটি প্রায় অভিন্ন!
স্টেভ ইস্কুরা

4
এফওয়াইআই, এই ওয়েল হ্যাশিং বৈশিষ্ট্যটি এখানে বর্ণিত হয়েছে: পর্যালোচনা অনুরোধ সিআর # 7118743: হ্যাশ-ভিত্তিক মানচিত্রের স্ট্রিংয়ের জন্য বিকল্প হ্যাশিং । এটি বচসা3 হ্যাশ ফাংশনের একটি বাস্তবায়ন।
ক্যামব্যাক

3

সেখানে প্রচুর অ্যাপ রয়েছে যা বড় ডেটা অ্যাপ্লিকেশনগুলিতে রেকর্ডে একটি ক্ষণস্থায়ী হ্যাশম্যাপ তৈরি করে। উদাহরণস্বরূপ এই পার্সার এবং সিরিয়ালাইজার। সিঙ্কক্রোনাইজড কালেকশন ক্লাসে যে কোনও সিঙ্ক্রোনাইজেশন স্থাপন করা সত্যিকারের গেটচা। আমার মতে, এটি অগ্রহণযোগ্য এবং ASAP ঠিক করা দরকার। দৃশ্যত 7u6, সিআর # 7118743 এ যে পরিবর্তনটি প্রবর্তিত হয়েছিল তা কোনও সিঙ্ক্রোনাইজেশন বা পারমাণবিক ক্রিয়াকলাপের প্রয়োজন ছাড়াই উল্টানো বা ঠিক করা উচিত।

কোনওভাবেই এটি স্ট্রিংবুফার এবং ভেক্টর এবং জ্যাশকে ১.১ / 1.2-এ সিঙ্ক্রোনাইজ করার জন্য হ্যাশ টেবিলের বিশাল ভুলটির কথা মনে করিয়ে দেয়। লোকেরা বছরের পর বছর ধরে সেই ভুলের জন্য মূল্য দিয়েছিল। সেই অভিজ্ঞতার পুনরাবৃত্তি করার দরকার নেই।


2

আপনার ব্যবহারের ধরণটি যুক্তিসঙ্গত বলে ধরে নিলে আপনি নিজের নিজস্ব সংস্করণ হ্যাশম্যাপটি ব্যবহার করতে চাইবেন।

কোডটির এই অংশটি হ্যাশের সংঘর্ষের কারণ হিসাবে অনেক বেশি শক্তিশালী হয়েছে, আক্রমণকারীদের পারফরম্যান্স সমস্যা তৈরি করতে বাধা দিচ্ছে ( বিশদ ) - এই সমস্যাটি ইতিমধ্যে অন্য কোনও উপায়ে মোকাবেলা করা হয়েছে বলে ধরে নেওয়া, আপনার মনে হয় না যে আপনার একেবারে সমন্বয় প্রয়োজন। তবে, আপনি যদি সিঙ্ক্রোনাইজেশন ব্যবহার করেন বা না করেন তবে এটি অপ্রাসঙ্গিক বলে মনে হচ্ছে আপনি হ্যাশম্যাপের নিজস্ব সংস্করণটি ব্যবহার করতে চাইবেন যাতে জেডিকে কী সরবরাহ করবে তাতে আপনি এতটা হতাশ করবেন না।

সুতরাং হয় আপনি সাধারণত সাধারণত কিছু অনুরূপ লিখুন এবং এটিতে নির্দেশ করুন, বা জেডিকে একটি শ্রেণিকে ওভাররাইড করুন। পরেরটি করতে, আপনি -Xbootclasspath/p:পরামিতি সহ বুটস্ট্র্যাপ শ্রেণিবদ্ধ করতে পারেন । তবে এটি "জাভা 2 রানটাইম এনভায়রনমেন্ট বাইনারি কোড লাইসেন্স" ( উত্স ) লঙ্ঘন করবে ।


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