ফ্যাক্টরিফাইন্ডার পারফরম্যান্স / খারাপ ক্যাচিং


9

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

একটি জিনিস আমি লক্ষ্য করেছি যে বিশেষত আমাদের কোডগুলির যে অংশগুলিতে আমরা কল করেছি TransformerFactory.newInstance(...)সেগুলি মারাত্মকভাবে ধীর হয়। আমি এটি সর্বদা একটি নতুন উদাহরণ তৈরি করার FactoryFinderপদ্ধতিতে ট্র্যাক করেছি । ইন javadoc আমি ক্যাশে সম্পর্কে নিম্নলিখিত নোট পাওয়া গেছে:findServiceProviderServiceLoaderServiceLoader

সরবরাহকারীরা অলসভাবে অবস্থিত এবং তাত্ক্ষণিকভাবে, যা চাহিদা অনুযায়ী on একটি পরিষেবা লোডার এখনও অবধি লোড করা সরবরাহকারীদের একটি ক্যাশে বজায় রাখে। পুনরুক্তি পদ্ধতিটির প্রতিটি অনুরোধ একটি পুনরাবৃত্তিকে ফেরত দেয় যা প্রথমে ক্যাশের সমস্ত উপাদানগুলি তাত্ক্ষণিক ক্রমে প্রদান করে এবং তারপরে অলসভাবে যে কোনও অবশিষ্ট সরবরাহকারীকে সনাক্ত করে এবং তত্ক্ষণাত প্রতিটিকে ক্যাশে যুক্ত করে। পুনরায় লোড পদ্ধতির মাধ্যমে ক্যাশে সাফ করা যায়।

এ পর্যন্ত সব ঠিকই. এটি ওপেনজেডিকে FactoryFinder#findServiceProviderপদ্ধতির একটি অংশ :

private static <T> T findServiceProvider(final Class<T> type)
        throws TransformerFactoryConfigurationError
    {
      try {
            return AccessController.doPrivileged(new PrivilegedAction<T>() {
                public T run() {
                    final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
                    final Iterator<T> iterator = serviceLoader.iterator();
                    if (iterator.hasNext()) {
                        return iterator.next();
                    } else {
                        return null;
                    }
                 }
            });
        } catch(ServiceConfigurationError e) {
            ...
        }
    }

প্রতিটি কল findServiceProviderকল ServiceLoader.load। এটি প্রতিবার একটি নতুন সার্ভিস লোডার তৈরি করে । এইভাবে দেখে মনে হচ্ছে যে সার্ভিস লোডার ক্যাশে মেকানিজমের কোনও ব্যবহার নেই। প্রতিটি কল অনুরোধকৃত সার্ভিস প্রোভাইডারের জন্য ক্লাসপাথটি স্ক্যান করে।

আমি ইতিমধ্যে যা চেষ্টা করেছি:

  1. আমি জানি যে আপনি কোনও সিস্টেমের সম্পত্তি সেট করতে পারেন যেমন javax.xml.transform.TransformerFactoryএকটি নির্দিষ্ট বাস্তবায়ন নির্দিষ্ট করতে চান । এইভাবে ফ্যাক্টরিফাইন্ডার সার্ভিস লোডার প্রক্রিয়া এবং এর সুপার দ্রুত ব্যবহার করে না। দুঃখজনকভাবে এটি একটি jvm প্রশস্ত সম্পত্তি এবং আমার jvm এ চলমান অন্যান্য জাভা প্রক্রিয়াগুলিকে প্রভাবিত করে। উদাহরণস্বরূপ আমার অ্যাপ্লিকেশনটি স্যাকসনের সাথে পাঠানো হয় এবং ব্যবহার করা উচিত com.saxonica.config.EnterpriseTransformerFactoryআমার কাছে আরও একটি অ্যাপ্লিকেশন রয়েছে যা স্যাকসনের সাথে জাহাজে আসে না। সিস্টেমের সম্পত্তি সেট করার সাথে সাথেই আমার অন্যান্য অ্যাপ্লিকেশন শুরু হতে ব্যর্থ হয়েছে, কারণ com.saxonica.config.EnterpriseTransformerFactoryএর ক্লাসপথে কোনও নেই । সুতরাং এটি আমার পক্ষে কোনও বিকল্প বলে মনে হয় না।
  2. আমি TransformerFactory.newInstanceযেখানেই ডেকে আছি তার প্রতিটি জায়গায় আমি ইতিমধ্যে রিফেক্টর করে ট্রান্সফর্মারফ্যাক্টরিটিকে ক্যাশে করেছি। তবে আমার নির্ভরতার বিভিন্ন জায়গা রয়েছে যেখানে আমি কোডটি রিফেক্টর করতে পারি না।

আমার প্রশ্নগুলি: ফ্যাক্টরিফাইন্ডার কেন একটি সার্ভিস লোডার পুনরায় ব্যবহার করে না? সিস্টেমের বৈশিষ্ট্যগুলি ব্যবহার না করে এই পুরো সার্ভিস লোডার প্রক্রিয়াটি আরও বাড়ানোর কোনও উপায় আছে কি? এটি কী জেডিকে পরিবর্তন করা যায় না যাতে কোনও ফ্যাক্টরিফাইন্ডার একটি সার্ভিস লোডার উদাহরণ পুনরায় ব্যবহার করে? এছাড়াও এটি একটি একক ফ্যাক্টরিফাইন্ডারের সাথে সুনির্দিষ্ট নয়। javax.xmlআমি এখনও অবধি প্যাকেজটিতে দেখেছি এই বাহাওয়ারটি সমস্ত ফ্যাক্টরিফাইন্ডার ক্লাসগুলির জন্য একই ।

আমি ওপেনডিজিডি 8/11 ব্যবহার করছি। আমার অ্যাপ্লিকেশনগুলি টমক্যাট 9 ইনস্ট্যান্সে মোতায়েন করা হয়েছে।

সম্পাদনা করুন: আরও বিশদ সরবরাহ করা

এখানে একটি একক এক্সএমএলআইনপুটফ্যাক্ট্রি.নিউআইন্সট্যান্স কলের জন্য কল স্ট্যাক রয়েছে: এখানে চিত্র বর্ণনা লিখুন

যেখানে বেশিরভাগ সংস্থান ব্যবহৃত হয় ServiceLoaders$LazyIterator.hasNextService। এই পদ্ধতিটি ফাইলটি getResourcesপড়ার জন্য ClassLoader এ কল করে META-INF/services/javax.xml.stream.XMLInputFactory। এই কলটি প্রতিটি সময় প্রায় 35 মিমি নেয়।

টমক্যাটকে এই ফাইলগুলি আরও দ্রুত সরবরাহ করা যাতে আরও ভালভাবে ক্যাশে দেওয়া যায় সেজন্য কোনও উপায় আছে?


আমি আপনার ফ্যাক্টরিফিন্ডার.জভা মূল্যায়নের সাথে একমত দেখে মনে হচ্ছে এটি সার্ভিস লোডারকে ক্যাশে করা উচিত। আপনি কি ওপেনজেডকের উত্সটি ডাউনলোড করে এটি তৈরি করার চেষ্টা করেছেন? আমি জানি যে বড় শব্দ মনে হচ্ছে তবে এটি নাও হতে পারে। এছাড়াও, ফ্যাক্টরিফাইন্ডার.জভা বিরুদ্ধে কোনও ইস্যু লিখে ফেলা উচিত এবং দেখুন যে কেউ সমস্যাটি তুলে ধরে সমাধানের প্রস্তাব দিচ্ছে কিনা।
djhallx

আপনি কি -Dআপনার Tomcatপ্রক্রিয়াতে পতাকা ব্যবহার করে সম্পত্তি সেট করার চেষ্টা করেছেন ? উদাহরণস্বরূপ: -Djavax.xml.transform.TransformerFactory=<factory class>.এটি অন্যান্য অ্যাপ্লিকেশনগুলির জন্য বৈশিষ্ট্যগুলি ওভাররাইড করা উচিত নয়। আপনার পোস্টটি ভাল বর্ণিত হয়েছে এবং সম্ভবত আপনি এটি ব্যবহার করে দেখেছেন তবে আমি নিশ্চিত করতে চাই। দেখুন Javax.xml.transform.TransformerFactory সিস্টেম সম্পত্তি কীভাবে সেট , কিভাবে HeapMemory বা জেভিএম আর্গুমেন্ট হুল বিড়াল মধ্যে সেট করতে
মাইকেল Ziober

উত্তর:


1

35 এমএস শোনার মত ডিস্ক অ্যাক্সেসের সময় জড়িত রয়েছে এবং এটি ওএস ক্যাশে করার ক্ষেত্রে কোনও সমস্যার দিকে ইঙ্গিত করে।

ক্লাসপথে কোনও ডিরেক্টরি / নন-জার এন্ট্রি রয়েছে যা জিনিসগুলি কমিয়ে দিতে পারে। এছাড়াও যদি উত্সটি চেক করা হয় না এমন প্রথম অবস্থানে উপস্থিত থাকে।

ClassLoader.getResourceওভাররাইড করা যেতে পারে আপনি (আমি বছর জন্য হুল বিড়াল স্পর্শ করেন নি) কনফিগারেশন মাধ্যমে থ্রেড প্রসঙ্গ বর্গ লোডার সেট করতে পারেন যদি পারেন বা শুধু Thread.setContextClassLoader


এর মত শব্দগুলি কাজ করতে পারে। আমার তাড়াতাড়ি বা পরে এ সম্পর্কে একবার নজর থাকবে। ধন্যবাদ!
ওয়াগনার মাইকেল

1

এটি ডিবাগ করতে আমি আরও 30 মিনিট সময় পেতে পারি এবং টমক্যাট কীভাবে রিসোর্স ক্যাচিং করে তা দেখেছি।

বিশেষত CachedResource.validateResources(যা উপরের শিখাগুলিতে পাওয়া যায়) আমার পক্ষে আগ্রহী ছিল। এটি এখনও বৈধ trueথাকলে এটি ফিরে আসে CachedResource:

protected boolean validateResources(boolean useClassLoaderResources) {
        long now = System.currentTimeMillis();
        if (this.webResources == null) {
            ...
        }

        // TTL check here!!
        if (now < this.nextCheck) {
            return true;
        } else if (this.root.isPackedWarFile()) {
            this.nextCheck = this.ttl + now;
            return true;
        } else {
            return false;
        }
    }

ক্যাশেড রিসোর্সের মতো মনে হয় আসলে বেঁচে থাকার সময় থাকে (টিটিএল)। টোমকেটে আসলে ক্যাশেটিটিএল কনফিগার করার একটি উপায় রয়েছে তবে আপনি কেবল এই মানটি বাড়িয়ে নিতে পারেন। রিসোর্স ক্যাচিং কনফিগারেশন সহজেই মনে হয় এটি নমনীয় নয়।

সুতরাং আমার টমকেটটির 5000 ডিগ্রি ডিফল্ট মান কনফিগার করা আছে। পারফরম্যান্স টেস্টিং করার সময় এটি আমাকে ফাঁকি দিয়েছে কারণ আমার অনুরোধের (গ্রাফ এবং স্টাফের দিকে তাকিয়ে) মাঝে আমার 5 সেকেন্ডের বেশি সময় ছিল। সে কারণেই আমার সমস্ত অনুরোধগুলি মূলত ক্যাশে ছাড়াই চলে এবং ZipFile.openপ্রতিবারই এটি ভারী করে তোলে ।

সুতরাং টমক্যাট কনফিগারেশনের সাথে আমি সত্যিই খুব অভিজ্ঞ না হওয়ায় এখানে সঠিক সমাধান কী তা আমি এখনও নিশ্চিত নই। ক্যাশেটিটিএল বাড়ানো ক্যাশেগুলি দীর্ঘায়িত করে তবে দীর্ঘকালীন সমস্যার সমাধান করে না।

সারসংক্ষেপ

আমি মনে করি এখানে আসলে দু'জন অপরাধী রয়েছেন।

  1. ফ্যাক্টরিফাইন্ডার ক্লাসগুলি সার্ভিস লোডার পুনরায় ব্যবহার করছে না। তারা এগুলি পুনরায় ব্যবহার না করার একটি বৈধ কারণ থাকতে পারে - যদিও আমি সত্যিই এটির একটি সম্পর্কে ভাবতে পারি না।

  2. টমক্যাট ওয়েব অ্যাপ্লিকেশন রিসোর্সের জন্য নির্দিষ্ট সময়ের পরে ক্যাশগুলি উচ্ছেদ করছে (ক্লাসপথে ফাইলগুলি - একটি ServiceLoaderকনফিগারেশনের মতো )

সার্ভিস লোডার শ্রেণীর জন্য সিস্টেম সম্পত্তি সংজ্ঞায়িত না করে এটি একত্রিত করুন এবং আপনি প্রতি cacheTtlসেকেন্ডে ধীর ফ্যাক্টরিফাইন্ডার কল পাবেন ।

আপাতত আমি দীর্ঘ সময়ের জন্য ক্রমবর্ধমান ক্যাশেটি নিয়ে বেঁচে থাকতে পারি। আমি টম হাটিনসকে ওভাররাইড করার পরামর্শটিও একবারে খেয়াল করতে Classloader.getResourcesপারি যদি আমার ধরণের ধারণা হয় যে এই পারফরম্যান্সের বাধা থেকে মুক্তি পাওয়ার পক্ষে এটি একটি কঠোর উপায়। এটি যদিও দেখার মতো হতে পারে।

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