একটি লুপে একটি স্ট্রিংবিল্ডার পুনরায় ব্যবহার করা কি ভাল?


101

আমি স্ট্রিংবিল্ডার ব্যবহার সম্পর্কিত একটি পারফরম্যান্স সম্পর্কিত প্রশ্ন করেছি। খুব দীর্ঘ লুপে আমি StringBuilderএটিকে পরিচালনা করছি এবং এটিকে অন্য পদ্ধতিতে পাস করছি :

for (loop condition) {
    StringBuilder sb = new StringBuilder();
    sb.append("some string");
    . . .
    sb.append(anotherString);
    . . .
    passToMethod(sb.toString());
}

StringBuilderপ্রতিটি লুপ চক্রে ইনস্ট্যান্ট করা কি ভাল সমাধান? এবং এর পরিবর্তে একটি মুছা কল আরও ভাল, নীচের মত?

StringBuilder sb = new StringBuilder();
for (loop condition) {
    sb.delete(0, sb.length);
    sb.append("some string");
    . . .
    sb.append(anotherString);
    . . .
    passToMethod(sb.toString());
}

উত্তর:


69

দ্বিতীয়টি আমার মিনি-বেঞ্চমার্কে প্রায় 25% দ্রুত।

public class ScratchPad {

    static String a;

    public static void main( String[] args ) throws Exception {
        long time = System.currentTimeMillis();
        for( int i = 0; i < 10000000; i++ ) {
            StringBuilder sb = new StringBuilder();
            sb.append( "someString" );
            sb.append( "someString2"+i );
            sb.append( "someStrin4g"+i );
            sb.append( "someStr5ing"+i );
            sb.append( "someSt7ring"+i );
            a = sb.toString();
        }
        System.out.println( System.currentTimeMillis()-time );
        time = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();
        for( int i = 0; i < 10000000; i++ ) {
            sb.delete( 0, sb.length() );
            sb.append( "someString" );
            sb.append( "someString2"+i );
            sb.append( "someStrin4g"+i );
            sb.append( "someStr5ing"+i );
            sb.append( "someSt7ring"+i );
            a = sb.toString();
        }
        System.out.println( System.currentTimeMillis()-time );
    }
}

ফলাফল:

25265
17969

নোট করুন যে এটি JRE 1.6.0_07 এর সাথে রয়েছে।


সম্পাদনাতে জন স্কিটির ধারণাগুলির উপর ভিত্তি করে এখানে সংস্করণ ২ 2. একই ফলাফল যদিও।

public class ScratchPad {

    static String a;

    public static void main( String[] args ) throws Exception {
        long time = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();
        for( int i = 0; i < 10000000; i++ ) {
            sb.delete( 0, sb.length() );
            sb.append( "someString" );
            sb.append( "someString2" );
            sb.append( "someStrin4g" );
            sb.append( "someStr5ing" );
            sb.append( "someSt7ring" );
            a = sb.toString();
        }
        System.out.println( System.currentTimeMillis()-time );
        time = System.currentTimeMillis();
        for( int i = 0; i < 10000000; i++ ) {
            StringBuilder sb2 = new StringBuilder();
            sb2.append( "someString" );
            sb2.append( "someString2" );
            sb2.append( "someStrin4g" );
            sb2.append( "someStr5ing" );
            sb2.append( "someSt7ring" );
            a = sb2.toString();
        }
        System.out.println( System.currentTimeMillis()-time );
    }
}

ফলাফল:

5016
7516

4
কেন এমন হচ্ছে হতে পারে তা বোঝাতে আমি আমার উত্তরে একটি সম্পাদনা যুক্ত করেছি। আমি কিছুক্ষণের মধ্যে আরও যত্ন সহকারে তাকিয়ে যাব (45 মিনিট)। দ্রষ্টব্য যে সংযোজন কলগুলিতে সংক্ষিপ্তকরণ করা কিছুটা প্রথম স্থানে স্ট্রিংবিল্ডার ব্যবহারের বিন্দু হ্রাস করে :)
জন স্কিটি

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

4
আমি এখনও প্রথম সংস্করণে যেতে চাই কারণ এটি ক্লিনার । তবে এটি ভাল যে আপনি আসলে বেঞ্চমার্কটি করেছেন :) পরবর্তী প্রস্তাবিত পরিবর্তনের জন্য: কনস্ট্রাক্টরের কাছে উপযুক্ত ক্ষমতা সহ # 1 চেষ্টা করুন।
জন স্কিটি

26
Sb.setLength (0) ব্যবহার করুন; পরিবর্তে, স্ট্রিংবিল্ডারের সামগ্রীগুলি পুনরায় তৈরি করার জন্য বা .delet () ব্যবহারের বিরুদ্ধে খালি করার দ্রুততম উপায়। নোট করুন যে এটি স্ট্রিংবুফারের ক্ষেত্রে প্রযোজ্য নয়, এর সম্মতিযুক্ত চেকগুলি গতির সুবিধাটি বাতিল করে দেয়।
পি অ্যারেহ

4
অপর্যাপ্ত উত্তর। পি অ্যারেহ এবং ডেভ জার্ভিস সঠিক। setLength (0) সবচেয়ে কার্যকর উত্তর খুব দূরে। স্ট্রিংবিল্ডার একটি চর অ্যারে দ্বারা সমর্থিত এবং পরিবর্তনীয়। .ToString () নামক স্থানে, চর অ্যারেটি অনুলিপি করা হয় এবং অপরিবর্তনীয় স্ট্রিং ব্যাক করতে ব্যবহৃত হয়। এই মুহুর্তে, স্ট্রিংবিল্ডারের পরিবর্তিত বাফারটি কেবল সন্নিবেশ পয়েন্টারটিকে শূন্যে ফিরিয়ে (.setLength (0) এর মাধ্যমে) পুনরায় ব্যবহার করা যেতে পারে। sb.toString আরও একটি অনুলিপি (অপরিবর্তনীয় চর অ্যারে) তৈরি করে, সুতরাং প্রতিটি পুনরাবৃত্তির জন্য .setLength (0) পদ্ধতির বিপরীতে দুটি বাফার প্রয়োজন যা লুপ প্রতি কেবল একটি নতুন বাফার প্রয়োজন।
ক্রিস

26

দ্রুততর:

public class ScratchPad {

    private static String a;

    public static void main( String[] args ) throws Exception {
        final long time = System.currentTimeMillis();

        // Pre-allocate enough space to store all appended strings.
        // StringBuilder, ultimately, uses an array of characters.
        final StringBuilder sb = new StringBuilder( 128 );

        for( int i = 0; i < 10000000; i++ ) {
            // Resetting the string is faster than creating a new object.
            // Since this is a critical loop, every instruction counts.
            sb.setLength( 0 );
            sb.append( "someString" );
            sb.append( "someString2" );
            sb.append( "someStrin4g" );
            sb.append( "someStr5ing" );
            sb.append( "someSt7ring" );
            setA( sb.toString() );
        }

        System.out.println( System.currentTimeMillis() - time );
    }

    private static void setA( final String aString ) {
        a = aString;
    }
}

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

এমনকি যদি এটি আরও জটিল ছিল এবং আপনি নিশ্চিতভাবে জানতেন যে অবজেক্ট ইনস্ট্যান্টেশনটি বাধা ছিল, তবে এটি মন্তব্য করুন।

এই উত্তর দিয়ে তিন রান:

$ java ScratchPad
1567
$ java ScratchPad
1569
$ java ScratchPad
1570

অন্য উত্তর দিয়ে তিন রান:

$ java ScratchPad2
1663
2231
$ java ScratchPad2
1656
2233
$ java ScratchPad2
1658
2242

তাত্পর্যপূর্ণ না হলেও, StringBuilderমেমরির পুনরায় বরাদ্দ রোধ করতে প্রাথমিক বাফার আকার নির্ধারণ করা একটি ছোট কর্মক্ষমতা অর্জন করবে।


4
এটি এখন পর্যন্ত সেরা উত্তর। স্ট্রিংবিল্ডার একটি চর অ্যারে দ্বারা সমর্থিত এবং পরিবর্তনীয়। .ToString () নামক স্থানে, চর অ্যারেটি অনুলিপি করা হয় এবং অপরিবর্তনীয় স্ট্রিং ব্যাক করতে ব্যবহৃত হয়। এই মুহুর্তে, স্ট্রিংবিল্ডারের পরিবর্তিত বাফারটি কেবল সন্নিবেশ পয়েন্টারটিকে শূন্যে ফিরিয়ে (.setLength (0) এর মাধ্যমে) পুনরায় ব্যবহার করা যেতে পারে। লুপের জন্য একটি ব্র্যান্ড নতুন স্ট্রিংবিল্ডার বরাদ্দের পরামর্শ দেয় সেগুলি উত্তরগুলি টের পাওয়া যাচ্ছে না বলে মনে হয় যে .toString এখনও অন্য অনুলিপি তৈরি করে, সুতরাং প্রতিটি পুনরাবৃত্তির জন্য .setLength (0) পদ্ধতির বিপরীতে দুটি বাফার প্রয়োজন যা লুপ প্রতি কেবল একটি নতুন বাফার প্রয়োজন।
ক্রিস

25

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

দ্বিতীয়ত, স্ট্রিংবিল্ডারের বৃহত্তম ইম্প্রোভমেন্টটি লুপটি চলাকালীন বড় হওয়া এড়াতে এটিকে প্রাথমিক আকার দেওয়ার থেকে আসে the

for (loop condition) {
  StringBuilder sb = new StringBuilder(4096);
}

4
আপনি সর্বদা কোঁকড়ানো বন্ধনী দিয়ে পুরো জিনিসটি স্কোপ করতে পারতেন, এইভাবে স্ট্রিংবিল্ডারের বাইরে আপনার কোনও ব্যবস্থা নেই।
এপাগা

@ এপাগা: এটি এখনও লুপের বাইরে। হ্যাঁ, এটি বাহ্যিক ক্ষেত্রকে দূষিত করে না, তবে পারফরম্যান্স উন্নতির জন্য কোডটি লেখার এটি একটি প্রাকৃতিক উপায় যা প্রসঙ্গে যাচাই করা হয়নি ।
জন স্কিটি

বা আরও ভাল, পুরো জিনিসটি তার নিজস্ব পদ্ধতিতে রাখুন। ;-) তবে আমি আবার শুনি: প্রসঙ্গ।
এপাগা

সুনির্দিষ্ট সংখ্যার পরিবর্তে প্রত্যাশিত আকারের সাথে আরম্ভ করা ভাল (4096) আপনার কোডটি একটি স্ট্রিং ফিরে আসতে পারে যা আকার 4096 আকারের একটি চর [[
জেডিকে

12

ঠিক আছে, আমি এখন বুঝতে পারছি কী চলছে, এবং এটি অর্থবোধ করে।

আমি এমন ছাপের মধ্যে ছিলাম যে toStringকেবলমাত্র char[]একটি স্ট্রিং কনস্ট্রাক্টরের অন্তর্নিহিত পাস করেছে যা অনুলিপি নেয় নি । তারপরে একটি অনুলিপি পরবর্তী "লিখন" অপারেশনে তৈরি করা হবে (উদাঃ delete)। আমার বিশ্বাস এই ছিল মামলাটি StringBufferকিছু পূর্ববর্তী সংস্করণে। (এটি এখন নয়)) তবে না - toStringকেবল অ্যারের (এবং সূচি এবং দৈর্ঘ্য) পাবলিক Stringকনস্ট্রাক্টরকে দেয় যা একটি অনুলিপি নেয়।

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

এটি সমস্তই দ্বিতীয় সংস্করণটিকে অবশ্যই আরও কার্যকর করার দিকে পরিচালিত করে - তবে একই সাথে আমি এখনও বলি এটি কুরুচিপূর্ণ কোড।


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


9

যেহেতু আমি এখনও এটি চিহ্নিত করা হয়নি বলে মনে করি না, কারণ সান জাভা সংকলকটিতে নির্মিত অপ্টিমাইজেশনের কারণে, যা স্ট্রিংবিল্ডারগুলি (স্ট্রিংবাফার্স প্রি-জে 2 এসই 5.0 পূর্ববর্তী) তৈরি করে যখন স্ট্রিং কনটেনটেশনগুলি দেখে, প্রশ্নের প্রথম উদাহরণটি সমান:

for (loop condition) {
  String s = "some string";
  . . .
  s += anotherString;
  . . .
  passToMethod(s);
}

যা আরও পাঠযোগ্য, আইএমও, আরও ভাল পন্থা। আপনার অনুকূলিতকরণের চেষ্টার ফলে কিছু প্ল্যাটফর্মে লাভ হতে পারে তবে সম্ভাব্যভাবে অন্যকে ক্ষতি করে।

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


4

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


যেখানে "অ-তুচ্ছ" মূল - বেঞ্চমার্কগুলি একটি ফর্মটি আনুপাতিকভাবে দ্রুততর হতে পারে, তবে আসল অ্যাপ্লিকেশনটিতে এটি কতটা সময় নিচ্ছে তা সম্পর্কে কোনও ইঙ্গিত ছাড়াই :)
জন স্কিটি

নীচে আমার উত্তরে মানদণ্ডটি দেখুন। দ্বিতীয় উপায় দ্রুত।
এপাগা

4
@ এপাগা: আপনার মানদণ্ডটি বাস্তব অ্যাপ্লিকেশনটির পারফরম্যান্স উন্নতির বিষয়ে খুব সামান্যই বলেছে, যেখানে স্ট্রিংবিল্ডার বরাদ্দের সময় নেওয়া অন্য লুপের সাথে তুলনামূলক ক্ষুদ্র হতে পারে। এজন্য বেঞ্চমার্কিংয়ে প্রসঙ্গটি গুরুত্বপূর্ণ।
জন স্কিটি

4
@ এপাগা: যতক্ষণ না তিনি এটিকে তার আসল কোড দিয়ে পরিমাপ করেছেন, ততক্ষণ তা আসলে কী তাৎপর্যপূর্ণ তা আমরা খুঁজে পাই না। লুপের প্রতিটি পুনরাবৃত্তির জন্য যদি প্রচুর কোড থাকে তবে আমি দৃ strongly়ভাবে সন্দেহ করি এটি এখনও অপ্রাসঙ্গিক হবে। "..." তে কী আছে তা আমরা জানি না
জন স্কিটি

4
(আমাকে ভুল বলবেন না, বিটিডব্লিউ - আপনার মাপদণ্ডের ফলাফলগুলি এখনও তাদের মধ্যে খুব আকর্ষণীয় I'm আমি মাইক্রোবেনমার্কস দ্বারা মুগ্ধ। বাস্তব জীবনের পরীক্ষা দেওয়ার আগে আমার কোডটি আকারের বাইরে নড়াচড়া করতে পছন্দ করি না))
জন স্কিটি

4

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

(আমার মতামত অন্য সবাই যা বলছে তার বিপরীত H


জিনিসটি হ'ল যে কোনও উপায়ে আগের মেমরিটি পুনরায় স্থানান্তর করতে হবে, কারণ বিদ্যমান ডেটাটি পূর্ববর্তী লুপ পুনরাবৃত্তির শেষে নতুন তৈরি স্ট্রিং ব্যবহার করছে।
জন স্কিটি

ওহ এটি বোধগম্য হয়, যদিও আমার কাছে ছিল যে টস্ট্রস্ট্রিং একটি নতুন স্ট্রিং উদাহরণ বরাদ্দ করে এবং ফিরে আসছিল এবং বিল্ডারের জন্য বাইট বাফার পুনরায় বরাদ্দের পরিবর্তে ক্লিয়ারিং করছিল।
cfeduke

এপাগার মানদণ্ড দেখায় যে ক্লিয়ারিং এবং পুনরায় ব্যবহার হ'ল প্রতিটি পাসে ইনস্ট্যান্টেশন লাভ।
cfeduke

1

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

private void clear() throws Exception {
    long time = System.currentTimeMillis();
    int maxLength = 0;
    StringBuilder sb = new StringBuilder();

    for( int i = 0; i < 10000000; i++ ) {
        // Resetting the string is faster than creating a new object.
        // Since this is a critical loop, every instruction counts.
        //
        sb.setLength( 0 );
        sb.append( "someString" );
        sb.append( "someString2" ).append( i );
        sb.append( "someStrin4g" ).append( i );
        sb.append( "someStr5ing" ).append( i );
        sb.append( "someSt7ring" ).append( i );
        maxLength = Math.max(maxLength, sb.toString().length());
    }

    System.out.println(maxLength);
    System.out.println("Clear buffer: " + (System.currentTimeMillis()-time) );
}

private void preAllocate() throws Exception {
    long time = System.currentTimeMillis();
    int maxLength = 0;

    for( int i = 0; i < 10000000; i++ ) {
        StringBuilder sb = new StringBuilder(82);
        sb.append( "someString" );
        sb.append( "someString2" ).append( i );
        sb.append( "someStrin4g" ).append( i );
        sb.append( "someStr5ing" ).append( i );
        sb.append( "someSt7ring" ).append( i );
        maxLength = Math.max(maxLength, sb.toString().length());
    }

    System.out.println(maxLength);
    System.out.println("Pre allocate: " + (System.currentTimeMillis()-time) );
}

public void testBoth() throws Exception {
    for(int i = 0; i < 5; i++) {
        clear();
        preAllocate();
    }
}

ফলাফলগুলি প্রত্যাশিত আকারের বাফার তৈরির চেয়ে 10% বেশি দ্রুত গতিতে পুনরায় ব্যবহার দেখায়।


1

এলওএল, আমি প্রথমবারের মতো স্ট্রিংবিল্ডারে স্ট্রিং সংমিশ্রণ করে লোকজনকে পারফরম্যান্সের তুলনা করতে দেখেছি। এই উদ্দেশ্যে, আপনি যদি "+" ব্যবহার করেন তবে এটি আরও দ্রুত হতে পারে; ডি। "স্থানীয়তা" ধারণা হিসাবে পুরো স্ট্রিংটির পুনরুদ্ধারের জন্য স্ট্রিংবিল্ডার ব্যবহারের উদ্দেশ্য।

আপনি যে স্ট্রিং মান ঘন ঘন পরিবর্তনের প্রয়োজন হয় না এমন দৃশ্যে স্ট্রিংবিল্ডার স্ট্রিং পুনরুদ্ধারের উচ্চতর পারফরম্যান্সের অনুমতি দেয়। এবং এটি স্ট্রিংবিল্ডার ব্যবহারের উদ্দেশ্য .. দয়া করে এর মূল উদ্দেশ্যটি এমআইএস-পরীক্ষা করবেন না ..

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


1

তাত্পর্যপূর্ণভাবে দ্রুত নয়, তবে আমার পরীক্ষাগুলি থেকে এটি 1.6.0_45 64 বিট ব্যবহার করে গড়ে কয়েক মিলিস দ্রুত হতে দেখায়: স্ট্রিংবিল্ডার.সেটলেন্থ (0) এর পরিবর্তে স্ট্রিংবিল্ডার.ডিলিট () ব্যবহার করুন:

time = System.currentTimeMillis();
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < 10000000; i++) {
    sb2.append( "someString" );
    sb2.append( "someString2"+i );
    sb2.append( "someStrin4g"+i );
    sb2.append( "someStr5ing"+i );
    sb2.append( "someSt7ring"+i );
    a = sb2.toString();
    sb2.setLength(0);
}
System.out.println( System.currentTimeMillis()-time );

1

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

 System.arraycopy(value, start+len, value, start, count-end);

এর পরে, স্ট্রিংবিল্ডার.ডিলেট () স্ট্রিংবিল্ডার কোডটিকে নতুন আকারে আপডেট করবে। স্ট্রিংবিল্ডার.সেটলেন্থ () কেবল নতুন আকারে স্ট্রিংবিল্ডার


0

প্রথমটি মানুষের পক্ষে ভাল। কিছু কিছু জেভিএম এর সংস্করণে যদি দ্বিতীয়টি কিছুটা দ্রুত হয়, তবে কী?

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

এই প্রশ্নটি কেন "প্রিয় প্রশ্ন" হিসাবে তাকাচ্ছেন? কারণ পারফরম্যান্স অপটিমাইজেশন এতটা মজাদার, তা বাস্তবিকই হোক বা না হোক।


এটি কেবল একাডেমিক প্রশ্ন নয়। যদিও বেশিরভাগ সময় (95% পড়ুন) আমি পঠনযোগ্যতা এবং রক্ষণাবেক্ষণযোগ্যতা পছন্দ করি, তবে সত্যিই এমন কিছু ঘটনা রয়েছে যা সামান্য উন্নতি বড় পার্থক্য করে ...
পিয়র লুইগি

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

0

আমি মনে করি না যে এটির মতো পারফরম্যান্সটি অপ্টিমাইজ করার চেষ্টা করার চেষ্টা করেছে। আজ (2019) দুটি আইটেমই আমার আই 5 ল্যাপটপে 100.000.000 লুপের জন্য প্রায় 11 সেকেন্ডে চলছে:

    String a;
    StringBuilder sb = new StringBuilder();
    long time = 0;

    System.gc();
    time = System.currentTimeMillis();
    for (int i = 0; i < 100000000; i++) {
        StringBuilder sb3 = new StringBuilder();
        sb3.append("someString");
        sb3.append("someString2");
        sb3.append("someStrin4g");
        sb3.append("someStr5ing");
        sb3.append("someSt7ring");
        a = sb3.toString();
    }
    System.out.println(System.currentTimeMillis() - time);

    System.gc();
    time = System.currentTimeMillis();
    for (int i = 0; i < 100000000; i++) {
        sb.setLength(0);
        sb.delete(0, sb.length());
        sb.append("someString");
        sb.append("someString2");
        sb.append("someStrin4g");
        sb.append("someStr5ing");
        sb.append("someSt7ring");
        a = sb.toString();
    }
    System.out.println(System.currentTimeMillis() - time);

==> 11000 এমসিতে (লুপের অভ্যন্তরে ঘোষণা) এবং 8236 এমসিতে (লুপের বাইরে ঘোষণা)

এমনকি যদি আমি কয়েক বিলিয়ন লুপের সাথে ঠিকানা অধিগ্রহণের জন্য প্রোগ্রামগুলি চালিত করি তবে 2 সেকেন্ডের পার্থক্য রয়েছে। ১০০ মিলিয়ন লুপের জন্য কোনও পার্থক্য হয় না কারণ প্রোগ্রামগুলি কয়েক ঘন্টা চলছে running আপনার যদি কেবলমাত্র একটি অ্যাপেন্ড স্টেটমেন্ট থাকে তবে জিনিসগুলি পৃথক রয়েছে তাও সচেতন থাকুন:

    System.gc();
    time = System.currentTimeMillis();
    for (int i = 0; i < 100000000; i++) {
        StringBuilder sb3 = new StringBuilder();
        sb3.append("someString");
            a = sb3.toString();
    }
    System.out.println(System.currentTimeMillis() - time);

    System.gc();
    time = System.currentTimeMillis();
    for (int i = 0; i < 100000000; i++) {
        sb.setLength(0);
        sb.delete(0, sb.length());
        sb.append("someString");
        a = sb.toString();
    }
    System.out.println(System.currentTimeMillis() - time);

==> 3416 ম্যাসি (লুপের অভ্যন্তরে), 3555 ম্যাসি (লুপের বাইরে) লুপের মধ্যে স্ট্রিংবিল্ডার তৈরি করা প্রথম বিবৃতি সেই ক্ষেত্রে দ্রুততর। এবং, যদি আপনি মৃত্যুদন্ডের ক্রম পরিবর্তন করেন তবে এটি আরও দ্রুত is

    System.gc();
    time = System.currentTimeMillis();
    for (int i = 0; i < 100000000; i++) {
        sb.setLength(0);
        sb.delete(0, sb.length());
        sb.append("someString");
        a = sb.toString();
    }
    System.out.println(System.currentTimeMillis() - time);

    System.gc();
    time = System.currentTimeMillis();
    for (int i = 0; i < 100000000; i++) {
        StringBuilder sb3 = new StringBuilder();
        sb3.append("someString");
            a = sb3.toString();
    }
    System.out.println(System.currentTimeMillis() - time);

==> 3638 মেসি (লুপের বাইরে), 2908 মেসি (লুপের অভ্যন্তরে)

শুভেচ্ছা, উলরিচ


-2

একবার ঘোষণা করুন, এবং প্রতিটি সময় নির্ধারণ করুন। এটি একটি অপ্টিমাইজেশনের চেয়ে আরও বেশি ব্যবহারিক এবং পুনরায় ব্যবহারযোগ্য ধারণা।

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