জাভাতে পারফরম্যান্সে ব্যতিক্রমগুলির প্রভাবগুলি কী?


496

প্রশ্ন: জাভাতে ব্যতিক্রম হ্যান্ডলিং কি আসলেই ধীর?

প্রচলিত জ্ঞান, পাশাপাশি গুগলের প্রচুর ফলাফল বলে যে জাভাতে সাধারণ প্রোগ্রাম প্রবাহের জন্য ব্যতিক্রমী যুক্তি ব্যবহার করা উচিত নয়। দুটি কারণ সাধারণত দেওয়া হয়,

  1. এটি সত্যিই ধীর - এমনকি নিয়মিত কোডের তুলনায় প্রস্থের ক্রমটিও ধীরে ধীরে (প্রদত্ত কারণগুলি ভিন্ন হয়),

এবং

  1. এটি অগোছালো কারণ লোকেরা ব্যতিক্রমী কোডগুলিতে কেবল ত্রুটিগুলি পরিচালনা করা আশা করে।

এই প্রশ্নটি প্রায় # 1।

উদাহরণ হিসাবে, এই পৃষ্ঠাটি জাভা ব্যতিক্রমকে "খুব ধীর" হিসাবে বর্ণনা করে এবং ব্যতিক্রম বার্তাটির স্ট্রিং তৈরির সাথে স্বচ্ছলতার সাথে সম্পর্কিত - "এই স্ট্রিংটি তখন ছুঁড়ে দেওয়া ব্যতিক্রম বস্তু তৈরিতে ব্যবহৃত হয় This এটি দ্রুত নয়" " জাভাতে কার্যকর ব্যতিক্রম হ্যান্ডলিং নিবন্ধটি বলেছে যে "এর কারণ ব্যতিক্রম হ্যান্ডলিংয়ের অবজেক্ট তৈরির দিক, যা এর ফলে ব্যতিক্রমগুলি সহজাতভাবে ধীর করে দেয়"। এর বাইরে আরও একটি কারণ হ'ল স্ট্যাক ট্রেস প্রজন্মই এটি হ্রাস করে।

আমার পরীক্ষা (জাভা হটস্পট 10.0, 32 বিট লিনাক্সে জাভা 1.6.0_07 ব্যবহার করে) নির্দেশ করে যে ব্যতিক্রম হ্যান্ডলিং নিয়মিত কোডের চেয়ে ধীর নয়। আমি একটি লুপে এমন কোনও পদ্ধতি চালানোর চেষ্টা করেছি যা কিছু কোড কার্যকর করে। পদ্ধতির শেষে, আমি ফিরে আসব বা নিক্ষেপ করব কিনা তা বোঝাতে একটি বুলিয়ান ব্যবহার করি । এইভাবে আসল প্রসেসিং একই রকম। আমি বিভিন্ন অর্ডারগুলিতে পদ্ধতিগুলি চালনার চেষ্টা করেছি এবং আমার পরীক্ষার সময়গুলি গড় গড় করে ভেবেছিলাম যে এটি জেভিএম উষ্ণ হতে পারে। আমার সমস্ত পরীক্ষায়, নিক্ষেপ কমপক্ষে দ্রুততর হিসাবে দ্রুত ছিল, যদি দ্রুত না হয় (3.1% পর্যন্ত দ্রুত)। আমার পরীক্ষাগুলি ভুল হওয়ার সম্ভাবনা সম্পর্কে আমি সম্পূর্ণ উন্মুক্ত, কিন্তু কোডের নমুনা, পরীক্ষার তুলনা, বা জাভাতে ব্যতিক্রম হ্যান্ডলিংয়ের প্রদর্শন করতে গত বা দু'বছরের ফলাফল হিসাবে আমি সেখানে কিছুই দেখিনি actually মন্থর।

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

কাগজে জাস্ট-ইন-সময় সংকলন সুদক্ষ জাভা ব্যতিক্রম হ্যান্ডলিং , লেখক যে সুপারিশ একা ব্যতিক্রম হ্যান্ডলার উপস্থিতি, এমনকি যদি কোন ব্যতিক্রম নিক্ষিপ্ত হয়, কোড সঠিকভাবে নিখুঁত থেকে JIT কম্পাইলার প্রতিরোধ যথেষ্ট, সুতরাং এটা গতি কমে ডাউন । আমি এই তত্ত্বটি এখনও পরীক্ষা করি নি।


8
আমি জানি আপনি 2) সম্পর্কে জিজ্ঞাসা করছিলেন না, তবে আপনার সত্যিকার অর্থেই স্বীকৃতি দেওয়া উচিত যে প্রোগ্রাম প্রবাহের জন্য ব্যতিক্রম ব্যবহার করা GOTOs ব্যবহারের চেয়ে ভাল নয়। কিছু লোক গোটসকে ডিফেন্ড করে, কিছু লোক আপনার সম্পর্কে যা বলছে তা রক্ষা করবে তবে আপনি যদি এমন কাউকে জিজ্ঞাসা করেন যিনি উভয় সময়ের জন্য প্রয়োগ ও রক্ষণাবেক্ষণ করেছেন, তারা আপনাকে বলবে যে উভয়ই নকশা অনুশীলনগুলি বজায় রাখা খুব কঠিন নয় (এবং সম্ভবত অভিশাপ দেবে) সেই ব্যক্তির নাম যাঁরা ভাবেন যে তারা যথেষ্ট স্মার্ট সেগুলি ব্যবহারের সিদ্ধান্ত নেওয়ার জন্য)।
বিল কে

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

14
সাধারণ নিয়ন্ত্রণ প্রবাহের জন্য ব্যতিক্রম ব্যবহার করে @ স্তন্যপায়ী জাভাতে একটি খারাপ ধারণা কারণ দৃষ্টান্ত পছন্দটি সেভাবেই হয়েছিল । ব্লাচ ইজে 2 পড়ুন - তিনি স্পষ্টভাবে বলেছেন যে, উদ্ধৃতি, (আইটেম 57) exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow- কেন এটি সম্পর্কে সম্পূর্ণ এবং বিস্তৃত ব্যাখ্যা প্রদান করা। এবং তিনি সেই লোক ছিলেন যিনি জাভা লিব লিখেছিলেন । সুতরাং, তিনি ক্লাসগুলির 'এপিআই চুক্তি সংজ্ঞায়িত করতে পারেন। / এই সম্পর্কে বিল কে সম্মত।

8
@ ওন্দ্রায়েকা যদি কিছু কাঠামো এটি করে (অ-ব্যতিক্রমী শর্তে ব্যতিক্রমগুলি ব্যবহার করে) তবে এটি ভাষাটির ব্যতিক্রম শ্রেণির চুক্তি ভঙ্গ করে ডিজাইনের মাধ্যমে ত্রুটিযুক্ত এবং ভেঙে গেছে। কিছু লোক লসি কোড লেখার কারণে এটি কম লম্পট করে না।

8
স্ট্যাকওভারফ্লো ডটকমের নির্মাতা ব্যতীত অন্য কোনওটি ব্যতিক্রম সম্পর্কে ভুল নয়। সফটওয়্যার বিকাশের সুবর্ণ নিয়ম কখনই সহজ জটিল এবং অনর্থক হয় না। তিনি লিখেছেন: "এটি সত্য যে একটি সাধারণ 3 লাইনের প্রোগ্রামটি প্রায়শই 48 টি লাইনগুলিতে প্রস্ফুটিত হয় যখন আপনি ভাল ত্রুটি পরীক্ষা করে দেখেন, তবে এটি জীবন, ..." এটি সরলতার নয়, খাঁটিতার জন্য অনুসন্ধান।
sf_jeff

উত্তর:


345

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

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

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

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

নিম্নলিখিত পরীক্ষার কোডটি দেখুন:

public class Test {
    int value;


    public int getValue() {
        return value;
    }

    public void reset() {
        value = 0;
    }

    // Calculates without exception
    public void method1(int i) {
        value = ((value + i) / i) << 1;
        // Will never be true
        if ((i & 0xFFFFFFF) == 1000000000) {
            System.out.println("You'll never see this!");
        }
    }

    // Could in theory throw one, but never will
    public void method2(int i) throws Exception {
        value = ((value + i) / i) << 1;
        // Will never be true
        if ((i & 0xFFFFFFF) == 1000000000) {
            throw new Exception();
        }
    }

    // This one will regularly throw one
    public void method3(int i) throws Exception {
        value = ((value + i) / i) << 1;
        // i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
        // an AND operation between two integers. The size of the number plays
        // no role. AND on 32 BIT always ANDs all 32 bits
        if ((i & 0x1) == 1) {
            throw new Exception();
        }
    }

    public static void main(String[] args) {
        int i;
        long l;
        Test t = new Test();

        l = System.currentTimeMillis();
        t.reset();
        for (i = 1; i < 100000000; i++) {
            t.method1(i);
        }
        l = System.currentTimeMillis() - l;
        System.out.println(
            "method1 took " + l + " ms, result was " + t.getValue()
        );

        l = System.currentTimeMillis();
        t.reset();
        for (i = 1; i < 100000000; i++) {
            try {
                t.method2(i);
            } catch (Exception e) {
                System.out.println("You'll never see this!");
            }
        }
        l = System.currentTimeMillis() - l;
        System.out.println(
            "method2 took " + l + " ms, result was " + t.getValue()
        );

        l = System.currentTimeMillis();
        t.reset();
        for (i = 1; i < 100000000; i++) {
            try {
                t.method3(i);
            } catch (Exception e) {
                // Do nothing here, as we will get here
            }
        }
        l = System.currentTimeMillis() - l;
        System.out.println(
            "method3 took " + l + " ms, result was " + t.getValue()
        );
    }
}

ফলাফল:

method1 took 972 ms, result was 2
method2 took 1003 ms, result was 2
method3 took 66716 ms, result was 2

ব্যাকগ্রাউন্ড প্রক্রিয়াগুলির মতো বিভ্রান্তিকর কারণগুলি অস্বীকার করার চেষ্টা করে ব্লকটি থেকে মন্দা খুব কম। কিন্তু ক্যাচ ব্লকটি সমস্ত কিছু মেরে ফেলেছিল এবং এটিকে 66 বার ধীর করে দিয়েছে!

আমি যেমন বলেছি, আপনি যদি ফলাফলটি ধরেন / ধরেন এবং একই পদ্ধতিতে (পদ্ধতি 3) ফেলে দেন তবে ফলাফলটি খুব খারাপ হবে না, তবে এটি একটি বিশেষ জেআইটি অপ্টিমাইজেশন যা আমি নির্ভর করতে পারি না ly এমনকি এই অপ্টিমাইজেশানটি ব্যবহার করার সময়, নিক্ষেপটি এখনও বেশ ধীর। সুতরাং আপনি এখানে কী করার চেষ্টা করছেন তা আমি জানি না, তবে চেষ্টা / ধরা / নিক্ষেপ করার চেয়ে এটি করার আরও ভাল উপায় অবশ্যই আছে।


7
দুর্দান্ত উত্তর তবে আমি কেবল এটি যোগ করতে চাই যতদূর আমি জানি, সিস্টেম.নানোটাইম () ব্যবহারকারীর পরিমাপের জন্য ব্যবহার করা উচিত, সিস্টেম কন্ট্রেন্টটাইমমিলিস () নয়।
সাইমন ফোর্সবার্গ

10
@ সিমোনআন্ড্রে ফোর্সবার্গের nanoTime()জাভা 1.5 প্রয়োজন এবং উপরের কোডটি লেখার জন্য আমি যে সিস্টেমটি ব্যবহার করেছি সেটিতে আমার কেবল জাভা 1.4 উপলব্ধ ছিল। এছাড়াও এটি অনুশীলনে একটি বিশাল ভূমিকা পালন করে না। উভয়ের মধ্যে একমাত্র পার্থক্য হ'ল একটি ন্যানোসেকেন্ড অন্যটি এক মিলি সেকেন্ড এবং এটি nanoTimeক্লক ম্যানিপুলেশন দ্বারা প্রভাবিত হয় না (যা অপ্রাসঙ্গিক, যদি না আপনি বা সিস্টেম প্রক্রিয়া পরীক্ষার কোডটি চলমান মুহুর্তে সিস্টেম ক্লকটি পরিবর্তন করে)। সাধারণত আপনি ঠিক, তবে nanoTimeঅবশ্যই ভাল পছন্দ।
মক্কি

2
এটি সত্যই লক্ষ করা উচিত যে আপনার পরীক্ষাটি চরম ক্ষেত্রে। আপনি একটি tryব্লকযুক্ত কোডের জন্য খুব ছোট পারফরম্যান্স হিট দেখান , তবে তা নয় throw। আপনার throwপরীক্ষাটি এর মধ্য দিয়ে যাওয়ার সময় 50% ব্যতিক্রম ছুঁড়ে দিচ্ছে try। এটি স্পষ্টভাবে এমন একটি পরিস্থিতি যেখানে ব্যর্থতা ব্যতিক্রমী নয় । কেবলমাত্র 10% এ কেটে ফেললে ব্যাপকভাবে পারফরম্যান্স হিট হয়। এই ধরণের পরীক্ষার সমস্যাটি হ'ল এটি ব্যতিক্রমগুলি পুরোপুরি ব্যবহার বন্ধ করতে উত্সাহিত করে। ব্যতিক্রমী কেস হ্যান্ডলিংয়ের জন্য ব্যতিক্রমগুলি ব্যবহার করে, আপনার পরীক্ষা যা দেখায় তার চেয়ে অনেক বেশি ভাল সম্পাদন করে।
নোট

1
@ নেটে সবার আগে, আমি খুব স্পষ্ট করে বলেছি যে এটি ব্যতিক্রমগুলি কীভাবে কার্যকর করা হয় তার উপর নির্ভর করে। আমি কেবলমাত্র একটি নির্দিষ্ট বাস্তবায়ন পরীক্ষা করছিলাম, তবুও প্রচুর পরিমাণ রয়েছে এবং ওরাকল প্রতিটি প্রকাশের সাথে একটি সম্পূর্ণ আলাদা চয়ন করতে পারে। দ্বিতীয়ত, যদি ব্যতিক্রমগুলি কেবল ব্যতিক্রমী হয় তবে সাধারণত তারা যা হয় তবে অবশ্যই প্রভাবটি কম হয়, এটি এতটাই সুস্পষ্ট যে আমি সত্যিই মনে করি না যে এটির একটি স্পষ্টভাবে উল্লেখ করতে হবে এবং এইভাবে আমি এখানে আপনার বিন্দুটি বুঝতে পারি না। এবং তৃতীয়ত, ব্যতিক্রমগুলি এটির খারাপ ব্যবহার করুন, সকলেই এতে সম্মত হন, তাই তাদেরকে অনেক যত্ন সহকারে ব্যবহার করা খুব ভাল জিনিস।
মক্কি

4
@ গ্লাইড এ থ্রো ক্লিনের মতো নয় return। এটি শরীরের মাঝখানে কোথাও একটি পদ্ধতি ফেলে দেয়, এমনকি কোনও অপারেশনের মাঝামাঝি সময়ে (এটি এখন পর্যন্ত কেবল 50% দ্বারা সম্পন্ন হয়েছে) এবং catchব্লকটি 20 স্ট্যাক ফ্রেমের উপরের দিকে হতে পারে (কোনও পদ্ধতিতে tryব্লক রয়েছে, পদ্ধতি কলিং 1, যাকে মেথড 2 বলে, যেটি মেহতড 3 বলে ..., এবং পদ্ধতি 20 তে একটি অপারেশনের মাঝখানে একটি ব্যতিক্রম ছুঁড়ে দেওয়া হয়)। স্ট্যাকটি অবশ্যই 20 ফ্রেমের উপরের দিকে আনইন্ড করা উচিত, সমস্ত অসম্পূর্ণ অপারেশন অবশ্যই পূর্বাবস্থায় ফেরানো উচিত (ক্রিয়াকলাপগুলি অর্ধেক সম্পন্ন করা উচিত নয়) এবং সিপিইউ নিবন্ধগুলি একটি পরিষ্কার অবস্থায় থাকা দরকার। এই সব সময় ব্যয় করে।
মক্কি

255

এফওয়াইআই, আমি মেকির যে পরীক্ষাটি করেছি তা বাড়িয়ে দিয়েছি:

method1 took 1733 ms, result was 2
method2 took 1248 ms, result was 2
method3 took 83997 ms, result was 2
method4 took 1692 ms, result was 2
method5 took 60946 ms, result was 2
method6 took 25746 ms, result was 2

প্রথম 3 মেকির মতো (আমার ল্যাপটপ স্পষ্টতই ধীর)।

মেথডুথ 4 মেথড 3 এর সাথে অভিন্ন, এটি বাদ দিয়ে এটি new Integer(1)করার চেয়ে একটি তৈরি করে throw new Exception()

মেথড 5 মেথড 3 এর মতো এটি new Exception()বাদ দিয়ে এটি ছোঁড়া ছাড়াই তৈরি করে ।

মেথডিয়াটি মেথড 3 এর মতো, এটি একটি নতুন তৈরির পরিবর্তে প্রাক-তৈরি ব্যতিক্রম (উদাহরণের পরিবর্তনশীল) ছুঁড়ে দেয়।

জাভাতে ব্যতিক্রম ছোঁড়ার ব্যয়ের বেশিরভাগ ব্যয় হ'ল স্ট্যাকের ট্রেস সংগ্রহ করতে ব্যয় করা সময়, যা ব্যতিক্রম বস্তু তৈরি হওয়ার পরে ঘটে। ব্যতিক্রম নিক্ষেপ করার আসল ব্যয়টি বৃহত্তর হলেও ব্যতিক্রম তৈরির ব্যয়ের চেয়ে যথেষ্ট কম।


48
+1 আপনার উত্তরটি মূল সমস্যাটিকে সম্বোধন করে - সময়টি খুলে ফেলা এবং স্ট্যাকটি ট্রেস করার সময় এবং দ্বিতীয়ত ত্রুটি নিক্ষেপ করা। আমি এটি চূড়ান্ত উত্তর হিসাবে নির্বাচিত হত।
ইঞ্জিনিয়ার

8
সুন্দর। ~ 70% ব্যতিক্রম তৈরি করছে, ~ 30% এটি নিক্ষেপ করছে। ভাল তথ্য।
চক্কে

1
@ বাসিল - উপরের সংখ্যাগুলি থেকে আপনার এটি নির্ধারণ করা উচিত।
হট লিক্স

1
এটি নির্দিষ্টকরণ বাস্তবায়ন হতে পারে। এই মানদণ্ডগুলির জন্য জাভার কোন সংস্করণ ব্যবহার করা হয়েছিল?
থরবজর্ন রাভন অ্যান্ডারসন

3
আমরা মন্তব্য করতে পারি যে স্ট্যান্ডার্ড কোডে, ব্যতিক্রমগুলি তৈরি এবং নিক্ষেপ বিরল ক্ষেত্রে দেখা যায় (রানটাইম বলতে আমি বোঝাতে চাইছি), যদি এটি না হয়, হয় রানটাইম শর্তগুলি খুব খারাপ হয়, বা নকশাটি নিজেই সমস্যা; উভয় ক্ষেত্রে পারফরম্যান্স কোনও উদ্বেগের বিষয় নয় ...
জিন-ব্যাপটিস্ট ইউনুস

70

আলেকসি শিপিলিভ একটি খুব বিশদ বিশ্লেষণ করেছিলেন যার মধ্যে তিনি বিভিন্ন অবস্থার সংমিশ্রণে জাভা ব্যতিক্রমগুলি চিহ্নিত করেছেন:

  • নতুন নির্মিত ব্যতিক্রম বনাম প্রাক-নির্মিত ব্যতিক্রম
  • স্ট্যাক ট্রেস সক্ষম বনাম অক্ষম
  • স্ট্যাক ট্রেস অনুরোধ বনাম কখনও অনুরোধ করা হয়নি
  • শীর্ষ স্তরে বনাম প্রতিটি স্তরে পুনর্নির্মাণ বনাম প্রতিটি স্তরে শৃঙ্খলাবদ্ধ / মোড়ানো অবস্থায় ধরা পড়ে
  • জাভা কল স্ট্যাক গভীরতার বিভিন্ন স্তর
  • কোনও ইনলাইনিং অপ্টিমাইজেশন বনাম চূড়ান্ত ইনলাইনিং বনাম ডিফল্ট সেটিংস
  • ব্যবহারকারীর দ্বারা সংজ্ঞায়িত ক্ষেত্রগুলি না পড়ুন পড়ুন

তিনি বিভিন্ন ত্রুটি ফ্রিকোয়েন্সি বিভিন্ন স্তরে একটি ত্রুটি কোড যাচাইয়ের পারফরম্যান্সের সাথে তাদের তুলনা করেন।

সিদ্ধান্তগুলি (তাঁর পোস্ট থেকে উদ্ধৃত ভারব্যাটিয়াম) ছিল:

  1. সত্যিই ব্যতিক্রমী ব্যতিক্রমগুলি সুন্দরভাবে অভিনয় করছেন nt আপনি যদি এগুলি ডিজাইন হিসাবে ব্যবহার করেন, এবং কেবলমাত্র নিয়মিত কোড দ্বারা পরিচালিত প্রচুর পরিমাণে অ-ব্যতিক্রমী মামলার মধ্যে সত্যিকারের ব্যতিক্রমী মামলাগুলি যোগাযোগ করেন, তবে ব্যতিক্রমগুলি ব্যবহার করা হচ্ছে পারফরম্যান্স জয়।

  2. ব্যতিক্রমগুলির কার্যকারিতা ব্যয়ের দুটি প্রধান উপাদান রয়েছে: এক্সেপশন তাত্ক্ষণিক হলে স্ট্যাক ট্রেস নির্মাণ এবং এক্সেপশন থ্রোর সময় স্ট্যান্ড আনওয়ানডিং।

  3. স্ট্যাক ট্রেস নির্মাণ ব্যয় ব্যতিক্রম তাত্ক্ষণিক মুহুর্তে স্ট্যাক গভীরতার সমানুপাতিক । এটি ইতিমধ্যে খারাপ কারণ পৃথিবীতে কে এই স্ট্রাকিং পদ্ধতিটি বলা হবে যে স্ট্যাক গভীরতা কে জানে? এমনকি যদি আপনি স্ট্যাক ট্রেস প্রজন্ম বন্ধ করে দেন এবং / অথবা ব্যতিক্রমগুলি ক্যাশে করেন তবে আপনি কেবল পারফরম্যান্স ব্যয়ের এই অংশ থেকে মুক্তি পেতে পারেন।

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

  5. আমরা যদি উভয় প্রভাবগুলি অপসারণ করি তবে ব্যতিক্রমগুলির কার্যকারিতা ব্যয় হ'ল স্থানীয় শাখার। এটি যত সুন্দরই লাগুক না কেন, এর অর্থ এই নয় যে আপনার ব্যতিক্রমগুলি যথারীতি নিয়ন্ত্রণ প্রবাহ হিসাবে ব্যবহার করা উচিত, কারণ সেক্ষেত্রে আপনি সংকলকটিকে অপ্টিমাইজ করার রহমতে রয়েছেন! আপনার কেবলমাত্র সেগুলি সত্যিকারের ব্যতিক্রমী ক্ষেত্রে ব্যবহার করা উচিত, যেখানে ব্যতিক্রমের ফ্রিকোয়েন্সিটি প্রকৃত ব্যতিক্রম বাড়াতে সম্ভাব্য দুর্ভাগ্য ব্যয়কে মোটা করে তোলে

  6. আশাবাদী নিয়মের অফ-থাম্বটি ব্যতিক্রমগুলির জন্য 10 ^ -4 ফ্রিকোয়েন্সি হিসাবে যথেষ্ট ব্যতিক্রমী বলে মনে হচ্ছে । এটি অবশ্যই ব্যতিক্রমগুলির ভারী ওজনগুলির উপর নির্ভর করে, ব্যতিক্রম হ্যান্ডলারদের সঠিক পদক্ষেপগুলি ইত্যাদি etc.

আপশটটি হ'ল যখন কোনও ব্যতিক্রম নিক্ষেপ করা হয় না, আপনি কোনও মূল্য পরিশোধ করেন না, সুতরাং যখন ব্যতিক্রমী শর্তটি যথেষ্ট বিরল ব্যতিক্রম হ্যান্ডলিং ifপ্রতিবার ব্যবহারের চেয়ে দ্রুত হয় । পুরো পোস্টটি খুব পঠনযোগ্য।


41

দুর্ভাগ্যক্রমে আমার উত্তরটি এখানে পোস্ট করা খুব দীর্ঘ। সুতরাং আমাকে এখানে সংক্ষেপে জানাতে এবং আপনাকে http://www.fuwjax.com/how-slow-are-java-exception/ এ উল্লেখ করুন কৌতূহল বিবরণের জন্য করুন।

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

সেন্টিনেল মানগুলি সাফল্যের ক্ষেত্রে এক শ্রেণি এবং ব্যর্থতার ক্ষেত্রে অন্য শ্রেণিতে ফিরে আসার প্রয়াস। আপনি এটিকে প্রায় নিক্ষেপের পরিবর্তে কোনও ব্যতিক্রম ফিরিয়ে দেওয়া হিসাবে প্রায় ভাবতে পারেন। সাফল্য অবজেক্ট সহ একটি ভাগ করা প্যারেন্ট ক্লাস প্রয়োজন এবং তারপরে সাফল্য বা ব্যর্থতার তথ্য পেতে একটি "উদাহরণস্বরূপ" চেক এবং একটি দম্পতি কাস্ট করা প্রয়োজন।

এটি প্রমাণিত হয়েছে যে প্রকার সুরক্ষার ঝুঁকিতে, সেন্টিনেল মানগুলি ব্যতিক্রমগুলির চেয়ে দ্রুত, তবে কেবল 2x এর ফ্যাক্টর দ্বারা। এখন, এটি অনেকটা মনে হতে পারে তবে 2x কেবল বাস্তবায়ন পার্থক্যের ব্যয়কেই coversেকে দেয়। অনুশীলনে, ফ্যাক্টরটি অনেক কম, যেহেতু আমাদের পদ্ধতির যেগুলি ব্যর্থ হতে পারে সেগুলি এই পৃষ্ঠার অন্য কোথাও নমুনা কোডের মতো কয়েকটি পাটিগণিত অপারেটরের চেয়ে আকর্ষণীয়।

অন্যদিকে, ফলাফলের মোড়কগুলি, প্রকারের সুরক্ষাটি একেবারেই ত্যাগ করবেন না। তারা সাফল্য এবং ব্যর্থতার তথ্যকে একটি একক ক্লাসে গুটিয়ে রাখে। সুতরাং "উদাহরণস্বরূপ" এর পরিবর্তে তারা একটি "ইসস্যাক্সেস ()" সরবরাহ করে এবং সাফল্য এবং ব্যর্থতা উভয় বস্তুর জন্য গ্রাহকরা। তবে, ব্যতিক্রমগুলি ব্যবহারের চেয়ে ফলাফল অবজেক্টগুলি প্রায় 2x ধীর slow দেখা যাচ্ছে যে প্রতিবার একটি নতুন র‍্যাপার অবজেক্ট তৈরি করা কখনও কখনও ব্যতিক্রম ছোঁড়ার চেয়ে ব্যয়বহুল।

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

ব্যতিক্রমগুলি সেন্ডিনেলগুলির চেয়ে নিরাপদ, ফলাফলের বস্তুগুলির চেয়ে দ্রুত এবং উভয়ের চেয়ে কম বিস্ময়কর। আমি প্রস্তাব দিচ্ছি না / চেষ্টা করুন / অন্যথায় যদি প্রতিস্থাপন প্রতিস্থাপন করা হয় তবে ব্যতিক্রমগুলি ব্যর্থতার প্রতিবেদন করার সঠিক উপায়, এমনকি ব্যবসায়ের যুক্তিতেও।

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


5
আমি কোনও নিয়ন্ত্রণ প্রয়োগের তুলনায় তিনটি বাস্তবায়নের দীর্ঘমেয়াদী কর্মক্ষমতা যাচাইয়ের সিদ্ধান্ত নিয়েছি যা রিপোর্ট না করেই ব্যর্থতার জন্য পরীক্ষা করে। প্রক্রিয়াটির ব্যর্থতার হার প্রায় 4%। একটি পরীক্ষার পুনরাবৃত্তি কৌশলগুলির মধ্যে একটির বিরুদ্ধে 10000 বার প্রক্রিয়াটি আহ্বান করে। প্রতিটি কৌশল 1000 বার পরীক্ষা করা হয় এবং শেষ 900 বার পরিসংখ্যান তৈরি করতে ব্যবহৃত হয়। ন্যানোসে গড় সময় এখানে: নিয়ন্ত্রন 338 ব্যতিক্রম 429 ফলাফল 348 সেন্টিনেল 345
ফুজ্যাক্স

2
কেবল মজাদার জন্য আমি ব্যতিক্রম পরীক্ষায় ফিলিইনস্ট্যাকট্রেস অক্ষম করেছি। এখন সময় এখন: নিয়ন্ত্রণ 347 ব্যতিক্রম 351 ফলাফল 364 সেন্টিনেল 355
ফুজ্যাক্স

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

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

@ ফুউজাক্স সুতরাং একটি ব্যতিক্রম ছুঁড়ে দেওয়া কি আপনার অ্যাকাউন্ট দ্বারা কোনও অবজেক্ট তৈরি করে না? নিশ্চিত নয় যে আমি এই যুক্তিটি বুঝতে পেরেছি। আপনি ব্যতিক্রম নিক্ষেপ করুন বা ফলাফলের বস্তুটি ফেরত দিন না কেন আপনি বস্তু তৈরি করছেন creating সেই অর্থে ফলাফল অবজেক্টগুলি ব্যতিক্রম ছোঁড়ার চেয়ে ধীর নয়।
ম্যাথিয়াস

20

আমি জাভা জন্য স্ট্যাকট্রেস ভরাট ছাড়াই @ মেক্কি এবং @ আমেরিকার দেওয়া উত্তরগুলি প্রসারিত করেছি ।

জাভা 7+ সহ, আমরা ব্যবহার করতে পারি Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace)। তবে জাভা for এর জন্য, এই প্রশ্নের জন্য আমার উত্তরটি দেখুন

// This one will regularly throw one
public void method4(int i) throws NoStackTraceThrowable {
    value = ((value + i) / i) << 1;
    // i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
    // an AND operation between two integers. The size of the number plays
    // no role. AND on 32 BIT always ANDs all 32 bits
    if ((i & 0x1) == 1) {
        throw new NoStackTraceThrowable();
    }
}

// This one will regularly throw one
public void method5(int i) throws NoStackTraceRuntimeException {
    value = ((value + i) / i) << 1;
    // i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
    // an AND operation between two integers. The size of the number plays
    // no role. AND on 32 BIT always ANDs all 32 bits
    if ((i & 0x1) == 1) {
        throw new NoStackTraceRuntimeException();
    }
}

public static void main(String[] args) {
    int i;
    long l;
    Test t = new Test();

    l = System.currentTimeMillis();
    t.reset();
    for (i = 1; i < 100000000; i++) {
        try {
            t.method4(i);
        } catch (NoStackTraceThrowable e) {
            // Do nothing here, as we will get here
        }
    }
    l = System.currentTimeMillis() - l;
    System.out.println( "method4 took " + l + " ms, result was " + t.getValue() );


    l = System.currentTimeMillis();
    t.reset();
    for (i = 1; i < 100000000; i++) {
        try {
            t.method5(i);
        } catch (RuntimeException e) {
            // Do nothing here, as we will get here
        }
    }
    l = System.currentTimeMillis() - l;
    System.out.println( "method5 took " + l + " ms, result was " + t.getValue() );
}

কোর আই 7, 8 জিবি র‌্যামে জাভা 1.6.0_45 এর সাথে আউটপুট:

method1 took 883 ms, result was 2
method2 took 882 ms, result was 2
method3 took 32270 ms, result was 2 // throws Exception
method4 took 8114 ms, result was 2 // throws NoStackTraceThrowable
method5 took 8086 ms, result was 2 // throws NoStackTraceRuntimeException

সুতরাং, এখনও যে পদ্ধতিগুলি মান দেয় তা দ্রুত, ব্যতিক্রম ছোঁড়ার পদ্ধতির তুলনায় দ্রুত। আইএমএইচও, আমরা সাফল্য এবং ত্রুটি প্রবাহ উভয়ের জন্য রিটার্নের ধরণগুলি ব্যবহার করে একটি পরিষ্কার এপিআই ডিজাইন করতে পারি না। স্ট্যাকট্রেস ছাড়াই ব্যতিক্রমগুলি ছুঁড়ে ফেলা পদ্ধতিগুলি সাধারণ ব্যতিক্রমগুলির চেয়ে 4-5 গুণ বেশি দ্রুত।

সম্পাদনা: NoStackTraceThrowable.java ধন্যবাদ @ গ্রেগ

public class NoStackTraceThrowable extends Throwable { 
    public NoStackTraceThrowable() { 
        super("my special throwable", null, false, false);
    }
}

আকর্ষণীয়, ধন্যবাদ এখানে নিখোঁজ শ্রেণির ঘোষণা:public class NoStackTraceThrowable extends Throwable { public NoStackTraceThrowable() { super("my special throwable", null, false, false); } }
গ্রেগ

বেজিং এ আপনি লিখেছেন With Java 7+, we can useকিন্তু পরে আপনি লিখেছেন Output with Java 1.6.0_45,তাই এটি জাভা 6 বা 7 ফলাফল?
WBAR

1
জাভা from থেকে ডাব্লুবিআর, আমাদের কেবল Throwableকন্সট্রাক্টরটি ব্যবহার করতে হবে যা তর্ক করেছে boolean writableStackTrace। তবে এটি জাভা 6 এবং নীচে উপস্থিত নেই। এজন্য আমি জাভা 6 এবং নীচে কাস্টম বাস্তবায়ন দিয়েছি। সুতরাং উপরের কোডটি জাভা 6 এবং নীচের জন্য। দয়া করে 2 য় প্যারা 1 ম লাইন পড়ুন।
মানিকান্ত

@ মানিকান্ত "আইএমএইচও, সাফল্য এবং ত্রুটি প্রবাহ উভয়ের জন্য আমরা রিটার্নের ধরণগুলি ব্যবহার করে একটি পরিষ্কার এপিআই ডিজাইন করতে পারি না" "- আমরা বিকল্পগুলি / ফলাফল / সম্ভবত যতগুলি ভাষা ব্যবহার করি তা ব্যবহার করতে পারি।
হিজাজমান

@ হেজাজ্জামান আমি সম্মত তবে Optionalজাভাতে কিছুটা দেরি হয়েছিল similar এর আগেও আমরা সাফল্য / ত্রুটিযুক্ত পতাকা সহ মোড়কের জিনিসগুলি ব্যবহার করি। তবে এটি কিছুটা হ্যাকস বলে মনে হয় এবং এটি আমার কাছে স্বাভাবিক মনে হয় না।
মানিকান্ত

8

কিছুক্ষণ আগে আমি দুটি পদ্ধতির সাহায্যে স্ট্রিংগুলিকে ইনটগুলিতে রূপান্তর করার তুলনামূলক পারফরম্যান্স পরীক্ষা করতে একটি ক্লাস লিখেছিলাম: (1) Integer.parseInt () কল করুন এবং ব্যতিক্রমটি ধরুন, বা (2) স্ট্রিংটিকে একটি রেজেক্সের সাথে মেলে এবং পার্সেইন্ট () কল করুন ম্যাচটি সফল হলেই। আমি সবচেয়ে কার্যকর উপায়ে রেইজেক্সটি ব্যবহার করেছি (যেমন, লুপটি অভ্যন্তরের আগে প্যাটার্ন এবং ম্যাচার অবজেক্ট তৈরি করা), এবং আমি ব্যতিক্রমগুলি থেকে স্ট্যাকট্রেসগুলি মুদ্রণ বা সংরক্ষণ করি নি।

দশ হাজার স্ট্রিংয়ের তালিকার জন্য, যদি সেগুলি সমস্ত বৈধ সংখ্যা হয় তবে পার্সেন্ট () পন্থাটি রেজেক্স পদ্ধতির চেয়ে চারগুণ দ্রুত ছিল। তবে যদি মাত্র ৮০% স্ট্রিং বৈধ হয় তবে রেজেক্স পার্সিয়ান্ট () হিসাবে দ্বিগুণ দ্রুত ছিল। এবং যদি 20% বৈধ হয়, যার অর্থ ব্যতিক্রমটি ফেলে দেওয়া হয়েছিল এবং 80% সময় ধরা পড়েছিল, রেজেক্সটি পার্সিয়ান্ট () হিসাবে প্রায় বিশ গুণ বেশি দ্রুত ছিল।

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


আপনি কোন JVM ব্যবহার করেছেন? এটি এখনও সূর্য- jdk 6 এর সাথে ধীর?
বেনিডিক্ট ওয়াল্ডভোগেল

উত্তরটি জমা দেওয়ার আগে আমি এটি খনন করে আবার জেডিকে 1.6u10 এর অধীনে এটিকে চালিত করেছিলাম এবং এটি আমার পোস্ট করা ফলাফল।
অ্যালান মুর

এটি খুব, খুব দরকারী! ধন্যবাদ। আমার সাধারণ ব্যবহারের ক্ষেত্রে ব্যবহারকারীর ইনপুট (যেমন কিছু ব্যবহার করে Integer.ParseInt()) পার্স করা দরকার এবং আমি প্রত্যাশা করি যে বেশিরভাগ সময় ব্যবহারকারীর ইনপুট সঠিক হবে, তাই আমার ব্যবহারের ক্ষেত্রে মনে হয় মাঝে মাঝে ব্যতিক্রম হিট নেওয়ার উপায় ।
মার্কভগতি

8

আমি মনে করি যে প্রথম নিবন্ধটি কল স্ট্যাককে আড়াল করা এবং একটি স্ট্যাক ট্রেসকে ব্যয়বহুল অংশ হিসাবে তৈরি করার কাজকে বোঝায় এবং দ্বিতীয় প্রবন্ধটি এটি না বলে, আমি মনে করি এটি অবজেক্ট তৈরির সবচেয়ে ব্যয়বহুল অংশ। জন রোজের একটি নিবন্ধ আছে যেখানে তিনি ব্যতিক্রমগুলি দ্রুত করার জন্য বিভিন্ন কৌশল বর্ণনা করেছেন । (পূর্বনির্ধারণ এবং একটি ব্যতিক্রম পুনরায় ব্যবহার, স্ট্যাক ট্রেস ব্যতীত ব্যতিক্রম ইত্যাদি)

তবে তবুও - আমি মনে করি এটি কেবল একটি প্রয়োজনীয় মন্দ হিসাবে বিবেচনা করা উচিত, একটি শেষ উপায়। জন এই কাজ করার কারণ হ'ল জেভিএমে উপলব্ধ অন্যান্য ভাষার বৈশিষ্ট্যগুলি অনুকরণ করা। নিয়ন্ত্রণ প্রবাহের ক্ষেত্রে ব্যতিক্রমগুলি ব্যবহার করার অভ্যাসটি আপনার উচিত নয়। বিশেষত পারফরম্যান্সের কারণে নয়! আপনি নিজে যেমন # 2 তে উল্লেখ করেছেন, আপনি আপনার কোডটিতে এইভাবে গুরুতর বাগগুলি মাস্কিংয়ের ঝুঁকিপূর্ণ হন এবং নতুন প্রোগ্রামারদের পক্ষে এটি রক্ষণাবেক্ষণ করা আরও শক্ত হবে।

জাভাতে থাকা মাইক্রোবেঞ্চমার্কগুলি সঠিকভাবে পাওয়া ঠিকই আশ্চর্যজনকভাবে কঠিন (আমাকে বলা হয়েছে), বিশেষত যখন আপনি জেআইটি অঞ্চলে প্রবেশ করেন, তাই আমি সত্যিই সন্দেহ করি যে ব্যতিক্রমগুলি বাস্তব জীবনে "ফিরতে" এর চেয়ে দ্রুততর। উদাহরণস্বরূপ, আমি সন্দেহ করি আপনার পরীক্ষায় 2 থেকে 5 স্ট্যাক ফ্রেমের মধ্যে কোথাও আছে? এখন ভাবুন আপনার কোডটি JBoss দ্বারা মোতায়েন করা একটি JSF উপাদান দ্বারা আহ্বান করা হবে। এখন আপনার কাছে স্ট্যাক ট্রেস থাকতে পারে যা বেশ কয়েকটি পৃষ্ঠার দীর্ঘ।

সম্ভবত আপনি আপনার পরীক্ষার কোড পোস্ট করতে পারে?


7

এই বিষয়গুলি সম্পর্কিত কিনা জানুন না তবে আমি একবার বর্তমান থ্রেডের স্ট্যাক ট্রেসের উপর নির্ভর করে একটি কৌশল প্রয়োগ করতে চেয়েছিলাম: আমি সেই পদ্ধতির নামটি আবিষ্কার করতে চেয়েছিলাম যা তাত্ক্ষণিক শ্রেণীর অভ্যন্তরে ইনস্ট্যান্টেশন ঘটায় (ইয়াপ, ধারণাটি পাগল, আমি একেবারে ছেড়ে দিয়েছি)। তাই আমি আবিষ্কার করেছি যে কলিং Thread.currentThread().getStackTrace()হয় অত্যন্ত (নেটিভ কারণে ধীর dumpThreadsপদ্ধতি যার ফলে এটি অভ্যন্তরীণভাবে ব্যবহার করে)।

সুতরাং জাভা Throwable, অনুরূপ, একটি স্থানীয় পদ্ধতি আছে fillInStackTrace। আমি মনে করি যে হত্যাকারী catchব্লকটি আগে বর্ণিত হয়েছে কোনওভাবে এই পদ্ধতির সম্পাদনকে ট্রিগার করে।

তবে আমি আপনাকে আরেকটি গল্প বলি ...

স্কালায় কিছু কার্যকর বৈশিষ্ট্যগুলি জেভিএম ব্যবহার করে সংকলিত হয় ControlThrowableযা এটি নিম্নলিখিত উপায়ে প্রসারিত Throwableও ওভাররাইড করে fillInStackTrace:

override def fillInStackTrace(): Throwable = this

সুতরাং আমি উপরের পরীক্ষাটি মানিয়ে নিয়েছি (চক্রের পরিমাণ দশ দ্বারা হ্রাস পেয়েছে, আমার মেশিনটি কিছুটা ধীর গতিতে :):

class ControlException extends ControlThrowable

class T {
  var value = 0

  def reset = {
    value = 0
  }

  def method1(i: Int) = {
    value = ((value + i) / i) << 1
    if ((i & 0xfffffff) == 1000000000) {
      println("You'll never see this!")
    }
  }

  def method2(i: Int) = {
    value = ((value + i) / i) << 1
    if ((i & 0xfffffff) == 1000000000) {
      throw new Exception()
    }
  }

  def method3(i: Int) = {
    value = ((value + i) / i) << 1
    if ((i & 0x1) == 1) {
      throw new Exception()
    }
  }

  def method4(i: Int) = {
    value = ((value + i) / i) << 1
    if ((i & 0x1) == 1) {
      throw new ControlException()
    }
  }
}

class Main {
  var l = System.currentTimeMillis
  val t = new T
  for (i <- 1 to 10000000)
    t.method1(i)
  l = System.currentTimeMillis - l
  println("method1 took " + l + " ms, result was " + t.value)

  t.reset
  l = System.currentTimeMillis
  for (i <- 1 to 10000000) try {
    t.method2(i)
  } catch {
    case _ => println("You'll never see this")
  }
  l = System.currentTimeMillis - l
  println("method2 took " + l + " ms, result was " + t.value)

  t.reset
  l = System.currentTimeMillis
  for (i <- 1 to 10000000) try {
    t.method4(i)
  } catch {
    case _ => // do nothing
  }
  l = System.currentTimeMillis - l
  println("method4 took " + l + " ms, result was " + t.value)

  t.reset
  l = System.currentTimeMillis
  for (i <- 1 to 10000000) try {
    t.method3(i)
  } catch {
    case _ => // do nothing
  }
  l = System.currentTimeMillis - l
  println("method3 took " + l + " ms, result was " + t.value)

}

সুতরাং, ফলাফলগুলি হ'ল:

method1 took 146 ms, result was 2
method2 took 159 ms, result was 2
method4 took 1551 ms, result was 2
method3 took 42492 ms, result was 2

আপনি দেখতে পাচ্ছেন, এর মধ্যে একমাত্র পার্থক্য method3এবং method4তারা হ'ল বিভিন্ন ধরণের ব্যতিক্রম ছুঁড়ে ফেলে। ইয়াপ, এর method4চেয়ে ধীরে ধীরে method1এবং method2পার্থক্যটি আরও অনেক বেশি গ্রহণযোগ্য।


6

আমি জেভিএম 1.5 এর সাথে কিছু পারফরম্যান্স টেস্টিং করেছি এবং ব্যতিক্রমগুলি ব্যবহার করা কমপক্ষে 2x ধীর ছিল। গড়: ব্যতিক্রম ব্যতীত ত্রিগুণ (3x) এর চেয়ে তুচ্ছ ছোট পদ্ধতিতে কার্যকর করার সময়। একটি ব্যতিক্রমী ছোট লুপ যে ব্যতিক্রমটি ধরেছিল তা স্ব-সময়ের মধ্যে 2x বৃদ্ধি পেয়েছিল।

আমি প্রোডাকশন কোডের পাশাপাশি মাইক্রো বেনমার্কগুলিতেও একই রকম সংখ্যা দেখেছি।

ব্যতিক্রমগুলি অবশ্যই ঘন ঘন বলা হয় এমন কোনও কিছুর জন্য অবশ্যই ব্যবহার করা উচিত নয় । এক সেকেন্ডে কয়েক হাজার ব্যতিক্রম ছুঁড়ে ফেলার ফলে বিশাল বোতল ঘাড় হতে পারে।

উদাহরণস্বরূপ, খুব বড় টেক্সট ফাইলে সমস্ত খারাপ মানগুলি খুঁজে পেতে "পূর্ণসংখ্যা.পার্সেন্ট (...)" ব্যবহার করে - খুব খারাপ ধারণা। (আমি এই ইউটিলিটি পদ্ধতিটি প্রোডাকশন কোডে কিল পারফরম্যান্স দেখেছি )

ব্যবহারকারীর জিইউআই ফর্মটিতে খারাপ মান জানাতে ব্যতিক্রম ব্যবহার করা, সম্ভবত পারফরম্যান্সের দিক থেকে খুব খারাপ নয়।

এটির ডিজাইনের একটি ভাল অনুশীলন হোক বা না হোক, আমি নিয়মটি সহ যাব: যদি ত্রুটিটি স্বাভাবিক / প্রত্যাশিত হয়, তবে একটি ফেরতের মান ব্যবহার করুন। যদি এটি অস্বাভাবিক হয় তবে একটি ব্যতিক্রম ব্যবহার করুন। উদাহরণস্বরূপ: ব্যবহারকারীদের ইনপুটগুলি পড়া, খারাপ মানগুলি স্বাভাবিক - একটি ত্রুটি কোড ব্যবহার করুন। একটি অভ্যন্তরীণ ইউটিলিটি ফাংশনে একটি মান পাস করে, খারাপ মানগুলি কলিং কোডের মাধ্যমে ফিল্টার করা উচিত - একটি ব্যতিক্রম ব্যবহার করুন।


আমাকে এমন কিছু জিনিস করতে পরামর্শ দিন যা করা ভাল: আপনার যদি ইন্টিজার.ভেলুওফ (স্ট্রিং) ব্যবহার না করে কোনও ফর্মের একটি নম্বর প্রয়োজন হয় তবে পরিবর্তে আপনার নিয়মিত এক্সপ্রেশন ম্যাচারের ব্যবহার বিবেচনা করা উচিত। আপনি প্যাটার্নটি পূর্বনির্মাণ করতে এবং পুনরায় ব্যবহার করতে পারেন যাতে ম্যাচারগুলি সস্তা হয়। তবে একটি জিইউআই ফর্মের মধ্যে, আইসভিড / বৈধতা / চেকফিল্ড রয়েছে বা আপনার কাছে যা সম্ভবত রয়েছে তা পরিষ্কার। এছাড়াও, জাভা 8 এর সাথে আমাদের ptionচ্ছিক মনড রয়েছে, সুতরাং সেগুলি ব্যবহার করার বিষয়টি বিবেচনা করুন। (উত্তরটি 9 বছরের পুরনো, তবে এখনও
!:

4

জাভা এবং সি # তে ব্যতিক্রমী পারফরম্যান্স পছন্দসই হওয়ার জন্য অনেকগুলি ছেড়ে যায়।

প্রোগ্রামারদের হিসাবে এটি কেবল আমাদের ব্যবহারিক কার্যকারণের কারণে "নিয়মিত ব্যতিক্রম ঘটায়" এই নিয়ম অনুসারে বাঁচতে বাধ্য করে।

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

এটি এক ধরণের গন্ডগোল। যদি ব্যতিক্রমগুলির আরও ভাল পারফরম্যান্স থাকে তবে আমরা এই আড়ম্বরপূর্ণ প্রতিমাগুলি এড়াতে পারতাম এবং ব্যতিক্রমগুলি সেগুলি ব্যবহার করার জন্য বোঝানো হয়েছিল ... কাঠামোগত ত্রুটি ফেরত সুবিধা হিসাবে as

আমি রিটার্ন-ভ্যালুগুলির কাছাকাছি কৌশল ব্যবহার করে বাস্তবায়ন ব্যতিক্রম প্রক্রিয়া দেখতে চাই, যাতে মানগুলি প্রত্যাবর্তনের আরও কাছাকাছি পারফরম্যান্স থাকতে পারি .. যেহেতু আমরা পারফরম্যান্স সংবেদনশীল কোডটিতে ফিরে আসি।

এখানে একটি কোড-নমুনা যা ব্যতিক্রম কার্যকারিতাটিকে ত্রুটি-রিটার্ন-মান সম্পাদনের সাথে তুলনা করে।

পাবলিক ক্লাস টেস্টআইটি {

int value;


public int getValue() {
    return value;
}

public void reset() {
    value = 0;
}

public boolean baseline_null(boolean shouldfail, int recurse_depth) {
    if (recurse_depth <= 0) {
        return shouldfail;
    } else {
        return baseline_null(shouldfail,recurse_depth-1);
    }
}

public boolean retval_error(boolean shouldfail, int recurse_depth) {
    if (recurse_depth <= 0) {
        if (shouldfail) {
            return false;
        } else {
            return true;
        }
    } else {
        boolean nested_error = retval_error(shouldfail,recurse_depth-1);
        if (nested_error) {
            return true;
        } else {
            return false;
        }
    }
}

public void exception_error(boolean shouldfail, int recurse_depth) throws Exception {
    if (recurse_depth <= 0) {
        if (shouldfail) {
            throw new Exception();
        }
    } else {
        exception_error(shouldfail,recurse_depth-1);
    }

}

public static void main(String[] args) {
    int i;
    long l;
    TestIt t = new TestIt();
    int failures;

    int ITERATION_COUNT = 100000000;


    // (0) baseline null workload
    for (int recurse_depth = 2; recurse_depth <= 10; recurse_depth+=3) {
        for (float exception_freq = 0.0f; exception_freq <= 1.0f; exception_freq += 0.25f) {            
            int EXCEPTION_MOD = (exception_freq == 0.0f) ? ITERATION_COUNT+1 : (int)(1.0f / exception_freq);            

            failures = 0;
            long start_time = System.currentTimeMillis();
            t.reset();              
            for (i = 1; i < ITERATION_COUNT; i++) {
                boolean shoulderror = (i % EXCEPTION_MOD) == 0;
                t.baseline_null(shoulderror,recurse_depth);
            }
            long elapsed_time = System.currentTimeMillis() - start_time;
            System.out.format("baseline: recurse_depth %s, exception_freqeuncy %s (%s), time elapsed %s ms\n",
                    recurse_depth, exception_freq, failures,elapsed_time);
        }
    }


    // (1) retval_error
    for (int recurse_depth = 2; recurse_depth <= 10; recurse_depth+=3) {
        for (float exception_freq = 0.0f; exception_freq <= 1.0f; exception_freq += 0.25f) {            
            int EXCEPTION_MOD = (exception_freq == 0.0f) ? ITERATION_COUNT+1 : (int)(1.0f / exception_freq);            

            failures = 0;
            long start_time = System.currentTimeMillis();
            t.reset();              
            for (i = 1; i < ITERATION_COUNT; i++) {
                boolean shoulderror = (i % EXCEPTION_MOD) == 0;
                if (!t.retval_error(shoulderror,recurse_depth)) {
                    failures++;
                }
            }
            long elapsed_time = System.currentTimeMillis() - start_time;
            System.out.format("retval_error: recurse_depth %s, exception_freqeuncy %s (%s), time elapsed %s ms\n",
                    recurse_depth, exception_freq, failures,elapsed_time);
        }
    }

    // (2) exception_error
    for (int recurse_depth = 2; recurse_depth <= 10; recurse_depth+=3) {
        for (float exception_freq = 0.0f; exception_freq <= 1.0f; exception_freq += 0.25f) {            
            int EXCEPTION_MOD = (exception_freq == 0.0f) ? ITERATION_COUNT+1 : (int)(1.0f / exception_freq);            

            failures = 0;
            long start_time = System.currentTimeMillis();
            t.reset();              
            for (i = 1; i < ITERATION_COUNT; i++) {
                boolean shoulderror = (i % EXCEPTION_MOD) == 0;
                try {
                    t.exception_error(shoulderror,recurse_depth);
                } catch (Exception e) {
                    failures++;
                }
            }
            long elapsed_time = System.currentTimeMillis() - start_time;
            System.out.format("exception_error: recurse_depth %s, exception_freqeuncy %s (%s), time elapsed %s ms\n",
                    recurse_depth, exception_freq, failures,elapsed_time);              
        }
    }
}

}

এবং ফলাফল এখানে:

baseline: recurse_depth 2, exception_freqeuncy 0.0 (0), time elapsed 683 ms
baseline: recurse_depth 2, exception_freqeuncy 0.25 (0), time elapsed 790 ms
baseline: recurse_depth 2, exception_freqeuncy 0.5 (0), time elapsed 768 ms
baseline: recurse_depth 2, exception_freqeuncy 0.75 (0), time elapsed 749 ms
baseline: recurse_depth 2, exception_freqeuncy 1.0 (0), time elapsed 731 ms
baseline: recurse_depth 5, exception_freqeuncy 0.0 (0), time elapsed 923 ms
baseline: recurse_depth 5, exception_freqeuncy 0.25 (0), time elapsed 971 ms
baseline: recurse_depth 5, exception_freqeuncy 0.5 (0), time elapsed 982 ms
baseline: recurse_depth 5, exception_freqeuncy 0.75 (0), time elapsed 947 ms
baseline: recurse_depth 5, exception_freqeuncy 1.0 (0), time elapsed 937 ms
baseline: recurse_depth 8, exception_freqeuncy 0.0 (0), time elapsed 1154 ms
baseline: recurse_depth 8, exception_freqeuncy 0.25 (0), time elapsed 1149 ms
baseline: recurse_depth 8, exception_freqeuncy 0.5 (0), time elapsed 1133 ms
baseline: recurse_depth 8, exception_freqeuncy 0.75 (0), time elapsed 1117 ms
baseline: recurse_depth 8, exception_freqeuncy 1.0 (0), time elapsed 1116 ms
retval_error: recurse_depth 2, exception_freqeuncy 0.0 (0), time elapsed 742 ms
retval_error: recurse_depth 2, exception_freqeuncy 0.25 (24999999), time elapsed 743 ms
retval_error: recurse_depth 2, exception_freqeuncy 0.5 (49999999), time elapsed 734 ms
retval_error: recurse_depth 2, exception_freqeuncy 0.75 (99999999), time elapsed 723 ms
retval_error: recurse_depth 2, exception_freqeuncy 1.0 (99999999), time elapsed 728 ms
retval_error: recurse_depth 5, exception_freqeuncy 0.0 (0), time elapsed 920 ms
retval_error: recurse_depth 5, exception_freqeuncy 0.25 (24999999), time elapsed 1121   ms
retval_error: recurse_depth 5, exception_freqeuncy 0.5 (49999999), time elapsed 1037 ms
retval_error: recurse_depth 5, exception_freqeuncy 0.75 (99999999), time elapsed 1141   ms
retval_error: recurse_depth 5, exception_freqeuncy 1.0 (99999999), time elapsed 1130 ms
retval_error: recurse_depth 8, exception_freqeuncy 0.0 (0), time elapsed 1218 ms
retval_error: recurse_depth 8, exception_freqeuncy 0.25 (24999999), time elapsed 1334  ms
retval_error: recurse_depth 8, exception_freqeuncy 0.5 (49999999), time elapsed 1478 ms
retval_error: recurse_depth 8, exception_freqeuncy 0.75 (99999999), time elapsed 1637 ms
retval_error: recurse_depth 8, exception_freqeuncy 1.0 (99999999), time elapsed 1655 ms
exception_error: recurse_depth 2, exception_freqeuncy 0.0 (0), time elapsed 726 ms
exception_error: recurse_depth 2, exception_freqeuncy 0.25 (24999999), time elapsed 17487   ms
exception_error: recurse_depth 2, exception_freqeuncy 0.5 (49999999), time elapsed 33763   ms
exception_error: recurse_depth 2, exception_freqeuncy 0.75 (99999999), time elapsed 67367   ms
exception_error: recurse_depth 2, exception_freqeuncy 1.0 (99999999), time elapsed 66990 ms
exception_error: recurse_depth 5, exception_freqeuncy 0.0 (0), time elapsed 924 ms
exception_error: recurse_depth 5, exception_freqeuncy 0.25 (24999999), time elapsed 23775  ms
exception_error: recurse_depth 5, exception_freqeuncy 0.5 (49999999), time elapsed 46326 ms
exception_error: recurse_depth 5, exception_freqeuncy 0.75 (99999999), time elapsed 91707 ms
exception_error: recurse_depth 5, exception_freqeuncy 1.0 (99999999), time elapsed 91580 ms
exception_error: recurse_depth 8, exception_freqeuncy 0.0 (0), time elapsed 1144 ms
exception_error: recurse_depth 8, exception_freqeuncy 0.25 (24999999), time elapsed 30440 ms
exception_error: recurse_depth 8, exception_freqeuncy 0.5 (49999999), time elapsed 59116   ms
exception_error: recurse_depth 8, exception_freqeuncy 0.75 (99999999), time elapsed 116678 ms
exception_error: recurse_depth 8, exception_freqeuncy 1.0 (99999999), time elapsed 116477 ms

রিটার্ন-মানগুলি পরীক্ষা করা এবং প্রচার করা বেসলাইন-নাল কলের তুলনায় কিছু ব্যয় যুক্ত করে এবং এই ব্যয়টি কল-গভীরতার সাথে সমানুপাতিক। 8 এর একটি কল-চেইন গভীরতায়, ত্রুটি-রিটার্ন-মান পরীক্ষা করার সংস্করণটি বেসলাইন সংস্করণ থেকে প্রায় 27% ধীর ছিল যা রিটার্ন মানগুলি পরীক্ষা করে না।

ব্যতিক্রম কর্মক্ষমতা, তুলনায়, কল-গভীরতার একটি ফাংশন নয়, ব্যতিক্রম ফ্রিকোয়েন্সি। যাইহোক, ব্যতিক্রম ফ্রিকোয়েন্সি বৃদ্ধি হিসাবে অবক্ষয় অনেক বেশি নাটকীয়। কেবলমাত্র 25% ত্রুটির ফ্রিকোয়েন্সিতে, কোডটি 24-টিআইএমইএস ধীর গতিতে চলে। 100% এর ত্রুটিযুক্ত ফ্রিকোয়েন্সি এ ব্যতিক্রম সংস্করণটি প্রায় 100-টিআইএমইএস ধীর।

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


3

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


2

এমনকি যদি কোনও ব্যতিক্রম ছুঁড়ে ফেলা ধীর না হয় তবে সাধারণ প্রোগ্রাম প্রবাহের জন্য ব্যতিক্রম ছুঁড়ে ফেলা খারাপ ধারণা। এইভাবে ব্যবহৃত এটি কোনও গোটোর সাথে সাদৃশ্যপূর্ণ ...

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


1
"স্বাভাবিক প্রোগ্রাম প্রবাহ" সংজ্ঞায়িত করা ভাল হবে। একটি ব্যবসায়িক প্রক্রিয়া ব্যর্থতা এবং পুনরুদ্ধারযোগ্য ব্যর্থতার জন্য চেক করা ব্যতিক্রম হিসাবে চেক করা ব্যতিক্রমগুলি ব্যবহার করার বিষয়ে অনেক কিছুই লেখা হয়েছে, সুতরাং এক অর্থে ব্যবসায়ের যুক্তিতে ব্যর্থতা এখনও সাধারণ প্রবাহ হিসাবে ভাবা যেতে পারে।
স্পেন্সার কোরোমস

2
@ স্পেন্সার কে: নামের ব্যতিক্রম হিসাবে একটি ব্যতিক্রমের অর্থ হ'ল একটি ব্যতিক্রমী পরিস্থিতি আবিষ্কার হয়েছিল (একটি ফাইল চলে গেল, একটি নেটওয়ার্ক হঠাৎ বন্ধ হয়ে গেল, ...)। এর দ্বারা বোঝা যাচ্ছে যে পরিস্থিতিটি ছিল অচিরাচরিত। যদি পরিস্থিতিটি ঘটে থাকে তা যদি পরীক্ষিত হয় তবে আমি এর জন্য একটি ব্যতিক্রম ব্যবহার করব না।
মক্কি

2
@ মেককি: ঠিক আছে। আমি সম্প্রতি এই সম্পর্কে কারও সাথে আলোচনা করেছি ... তারা একটি বৈধকরণ কাঠামো লিখছিল এবং বৈধতা ব্যর্থতার ক্ষেত্রে ব্যতিক্রম ছুঁড়ে মারছিল। আমি মনে করি এটি একটি খারাপ ধারণা কারণ এটি বেশ সাধারণ হবে। আমি বরং পদ্ধতিটি একটি ভ্যালিডেশন রেজাল্ট ফেরত দেখতে চাই।
ব্যবহারকারী38051

2
নিয়ন্ত্রণ প্রবাহের ক্ষেত্রে, একটি ব্যতিক্রম একটি breakবা returnনয়, এর সাথে সাদৃশ্য goto
হট লিক্স

3
এখানে প্রচুর প্রোগ্রামিং প্যারাডাইম রয়েছে। কোনও একক "স্বাভাবিক প্রবাহ" থাকতে পারে না, আপনি এর দ্বারা যা বোঝায়। মূলত, ব্যতিক্রম প্রক্রিয়াটি বর্তমান ফ্রেমটি দ্রুত রেখে একটি নির্দিষ্ট পয়েন্ট অবধি স্ট্যাকটি আনওয়াইন্ড করার একমাত্র উপায়। "ব্যতিক্রম" শব্দটি এর "অপ্রত্যাশিত" প্রকৃতি সম্পর্কে কিছুই বোঝায় না। একটি দ্রুত উদাহরণ: রাউটিংয়ের পথে যখন কিছু পরিস্থিতি দেখা দেয় তখন ওয়েব অ্যাপ্লিকেশনগুলি থেকে 404 গুলি "নিক্ষেপ করা" খুব স্বাভাবিক। ব্যতিক্রম নিয়ে সেই যুক্তি কেন প্রয়োগ করা হবে না? অ্যান্টি-প্যাটার্ন কী?
দেহধারী

2

কেবল তুলনা করুন যাক Integer.parseInt নিম্নলিখিত পদ্ধতিতে, যা কেবলমাত্র ব্যতিক্রম ছোঁড়ার পরিবর্তে অন্বেষণযোগ্য ডেটার ক্ষেত্রে একটি ডিফল্ট মান প্রদান করে:

  public static int parseUnsignedInt(String s, int defaultValue) {
    final int strLength = s.length();
    if (strLength == 0)
      return defaultValue;
    int value = 0;
    for (int i=strLength-1; i>=0; i--) {
      int c = s.charAt(i);
      if (c > 47 && c < 58) {
        c -= 48;
        for (int j=strLength-i; j!=1; j--)
          c *= 10;
        value += c;
      } else {
        return defaultValue;
      }
    }
    return value < 0 ? /* übergebener wert > Integer.MAX_VALUE? */ defaultValue : value;
  }

যতক্ষণ আপনি "বৈধ" ডেটাতে উভয় পদ্ধতি প্রয়োগ করেন ততক্ষণে তারা উভয়ই প্রায় একই হারে কাজ করবে (যদিও Integer.parseInt আরও জটিল ডেটা পরিচালনা করতে পরিচালিত হয়)। তবে আপনি অবৈধ ডেটা পার্স করার চেষ্টা করার সাথে সাথে (উদাহরণস্বরূপ "abc" 1.000.000 বার পার্স করার জন্য), পারফরম্যান্সের পার্থক্যটি অপরিহার্য হওয়া উচিত।


2

ব্যতিক্রম কর্মক্ষমতা সম্পর্কে দুর্দান্ত পোস্টটি হ'ল:

https://shipilev.net/blog/2014/exceptional-performance/

ইনস্টল করে বনাম পুনরায় ব্যবহার করা, স্ট্যাক ট্রেস এবং ছাড়াই ইত্যাদি:

Benchmark                            Mode   Samples         Mean   Mean error  Units

dynamicException                     avgt        25     1901.196       14.572  ns/op
dynamicException_NoStack             avgt        25       67.029        0.212  ns/op
dynamicException_NoStack_UsedData    avgt        25       68.952        0.441  ns/op
dynamicException_NoStack_UsedStack   avgt        25      137.329        1.039  ns/op
dynamicException_UsedData            avgt        25     1900.770        9.359  ns/op
dynamicException_UsedStack           avgt        25    20033.658      118.600  ns/op

plain                                avgt        25        1.259        0.002  ns/op
staticException                      avgt        25        1.510        0.001  ns/op
staticException_NoStack              avgt        25        1.514        0.003  ns/op
staticException_NoStack_UsedData     avgt        25        4.185        0.015  ns/op
staticException_NoStack_UsedStack    avgt        25       19.110        0.051  ns/op
staticException_UsedData             avgt        25        4.159        0.007  ns/op
staticException_UsedStack            avgt        25       25.144        0.186  ns/op

স্ট্যাক ট্রেস গভীরতার উপর নির্ভর করে:

Benchmark        Mode   Samples         Mean   Mean error  Units

exception_0000   avgt        25     1959.068       30.783  ns/op
exception_0001   avgt        25     1945.958       12.104  ns/op
exception_0002   avgt        25     2063.575       47.708  ns/op
exception_0004   avgt        25     2211.882       29.417  ns/op
exception_0008   avgt        25     2472.729       57.336  ns/op
exception_0016   avgt        25     2950.847       29.863  ns/op
exception_0032   avgt        25     4416.548       50.340  ns/op
exception_0064   avgt        25     6845.140       40.114  ns/op
exception_0128   avgt        25    11774.758       54.299  ns/op
exception_0256   avgt        25    21617.526      101.379  ns/op
exception_0512   avgt        25    42780.434      144.594  ns/op
exception_1024   avgt        25    82839.358      291.434  ns/op

অন্যান্য বিবরণের জন্য (জেআইটি থেকে এক্স 64 এসেম্বলার সহ) আসল ব্লগ পোস্টটি পড়ুন।

তার মানে হাইবারনেট / স্প্রিং / ইত্যাদি-ইই-শিট ব্যতিক্রমগুলি (এক্সডি) এবং পুনরায় লেখার জন্য অ্যাপ্লিকেশন নিয়ন্ত্রণ প্রবাহ ব্যতিক্রমগুলি থেকে দূরে রয়েছে (এটিকে প্রতিস্থাপন করুন continure/ breakএবং পদ্ধতিযুক্ত booleanকল থেকে সি এর মতো পতাকাগুলি ফিরিয়ে দেওয়া) আপনার অ্যাপ্লিকেশন 10x-100x এর কার্যকারিতা উন্নতি করবে আপনি কতবার এগুলি ছুঁড়েছেন তার উপর নির্ভর করে))


0

আমি মেথির উত্তরটি পরিবর্তিত করেছি মেথডিয়া 1 এর কলিং পদ্ধতিতে একটি বুলিয়ান এবং একটি চেক ফেরত দেওয়ার জন্য, কারণ আপনি কেবলমাত্র কোনও ব্যতিক্রম ব্যতীত প্রতিস্থাপন করতে পারবেন না। দুটি রান করার পরেও, মেথড 1 তত দ্রুততম বা পদ্ধতি 2 এর মতো দ্রুত ছিল।

কোডটির স্ন্যাপশটটি এখানে:

// Calculates without exception
public boolean method1(int i) {
    value = ((value + i) / i) << 1;
    // Will never be true
    return ((i & 0xFFFFFFF) == 1000000000);

}
....
   for (i = 1; i < 100000000; i++) {
            if (t.method1(i)) {
                System.out.println("Will never be true!");
            }
    }

এবং ফলাফল:

চালান ঘ

method1 took 841 ms, result was 2
method2 took 841 ms, result was 2
method3 took 85058 ms, result was 2

রান 2

method1 took 821 ms, result was 2
method2 took 838 ms, result was 2
method3 took 85929 ms, result was 2

0

একটি ব্যতিক্রম পরিচালনা করার জন্য বোঝানো হয় রান সময়ে অপ্রত্যাশিত অবস্থার শুধুমাত্র।

সংকলনের সময় সম্পন্ন করা যায় এমন সাধারণ বৈধতার জায়গায় একটি ব্যতিক্রম ব্যবহার কার্যকরকরণের সময় পর্যন্ত বৈধতাটিকে বিলম্বিত করবে। এর ফলে প্রোগ্রামের দক্ষতা হ্রাস পাবে।

একটি সাধারণ if..else বৈধতা ব্যবহার করার পরিবর্তে একটি ব্যতিক্রম ছুঁড়ে দেওয়া কোড লিখতে এবং বজায় রাখতে জটিল করে তোলে।


-3

প্রোগ্রামেমেটিকভাবে ডেটা পরীক্ষা করা ব্যতিক্রম গতি সম্পর্কে আমার মতামত।

অনেক ক্লাসের স্ট্রিং টু মান রূপান্তরকারী ছিল (স্ক্যানার / পার্সার), শ্রদ্ধেয় এবং সুপরিচিত গ্রন্থাগারগুলিও;)

সাধারণত ফর্ম আছে

class Example {
public static Example Parse(String input) throws AnyRuntimeParsigException
...
}

ব্যতিক্রম নামটি উদাহরণস্বরূপ, সাধারণত আনচেকড (রানটাইম) হয়, তাই ঘোষণাটি কেবলমাত্র আমার ছবি

কখনও কখনও দ্বিতীয় ফর্ম উপস্থিত:

public static Example Parse(String input, Example defaultValue)

কখনও নিক্ষেপ করা হয় না

যখন দ্বিতীয়টি না পাওয়া যায় (বা প্রোগ্রামার খুব কম ডক্স পড়ে এবং কেবল প্রথমে ব্যবহার করে), নিয়মিত প্রকাশের সাথে এই জাতীয় কোড লিখুন। নিয়মিত প্রকাশটি শীতল, রাজনৈতিকভাবে সঠিক ইত্যাদি:

Xxxxx.regex(".....pattern", src);
if(ImTotallySure)
{
  Example v = Example.Parse(src);
}

এই কোড সহ প্রোগ্রামাররা ব্যতিক্রম ব্যয় করতে পারে না। তবে কখনও কখনও ব্যতিক্রমের স্বল্প খরচে বনাম নিয়মিত এক্সপ্রেশনগুলির খুব উচ্চ ব্যয়ের তুলনাযোগ্য।

আমি প্রায় সবসময় এই প্রসঙ্গে ব্যবহার করি

try { parse } catch(ParsingException ) // concrete exception from javadoc
{
}

স্ট্যাকট্রেস ইত্যাদি বিশ্লেষণ না করে, আমি বিশ্বাস করি আপনার বক্তৃতার পরে বেশ গতি।

ভয় পাবেন না ব্যতিক্রম


-5

ব্যতিক্রমগুলি কেন সাধারণ রিটার্নের চেয়ে ধীর হওয়া উচিত?

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

ভাল প্রশ্ন এবং আমি এই বিষয়ে আরও তথ্যের জন্য অপেক্ষা করছি!


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