পারফরম্যান্স জরুরী হলে আমার কি জাওয়ার স্ট্রিং.ফর্ম্যাট () ব্যবহার করা উচিত?


215

লগ আউটপুট ইত্যাদির জন্য আমাদের সর্বদা স্ট্রিংস তৈরি করতে হবে। আমরা কখন জেডিকে সংস্করণ ব্যবহার করব তা শিখেছিStringBuffer (অনেকগুলি সংযোজন, থ্রেড নিরাপদ) এবং StringBuilder(অনেকগুলি সংযোজন, নন-থ্রেড-নিরাপদ)।

ব্যবহার করার পরামর্শ কি String.format() ? এটি কি দক্ষ, বা যেখানে আমরা পারফরম্যান্স গুরুত্বপূর্ণ সেখানে ওয়ান-লাইনারদের জন্য কনট্যাকটেশন দিয়ে বাধ্য হতে বাধ্য?

যেমন কুরুচিপূর্ণ পুরাতন স্টাইল,

String s = "What do you get if you multiply " + varSix + " by " + varNine + "?";

বনাম পরিপাটি করা নতুন স্টাইল (স্ট্রিং.ফর্ম্যাট, যা সম্ভবত ধীরে ধীরে),

String s = String.format("What do you get if you multiply %d by %d?", varSix, varNine);

দ্রষ্টব্য: আমার নির্দিষ্ট ব্যবহারের কেসটি আমার কোড জুড়ে শত শত 'ওয়ান-লাইনার' লগ স্ট্রিং। তারা একটি লুপ জড়িত না, তাই StringBuilderখুব ভারী ওজন। আমি String.format()বিশেষভাবে আগ্রহী ।


28
আপনি এটি পরীক্ষা করেন না কেন?
এড এস

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

9
@ পিটার, না এটি মানুষের দ্বারা বাস্তব সময়ে পড়ার জন্য একেবারেই নয়! জিনিসগুলি ভুল হয়ে গেলে বিশ্লেষণে সহায়তা করার জন্য এটি রয়েছে। লগ আউটপুট সাধারণত প্রতি সেকেন্ডে কয়েক হাজার লাইন হবে, সুতরাং এটি দক্ষ হওয়া দরকার।
এয়ার

5
আপনি যদি প্রতি সেকেন্ডে কয়েক হাজার লাইন তৈরি করে থাকেন, আমি পরামর্শ দেব 1) আরও ছোট পাঠ্য ব্যবহার করুন, এমনকি প্লেইন সিএসভি বা বাইনারি হিসাবে কোনও পাঠ্য 2) স্ট্রিং মোটেও ব্যবহার করবেন না, আপনি তৈরি না করেই বাইটবফারে ডেটা লিখতে পারবেন কোনও বস্তু (পাঠ্য বা বাইনারি হিসাবে) 3) ডিস্ক বা সকেটে ডেটা লেখার ব্যাকগ্রাউন্ড। আপনার প্রতি সেকেন্ডে প্রায় 1 মিলিয়ন লাইন ধরে রাখতে সক্ষম হওয়া উচিত। (মূলত আপনার ডিস্ক সাবসিস্টেমটি যতটা অনুমতি দেবে) আপনি এটি 10x এর বিস্ফোরণ পেতে পারেন।
পিটার লরে

7
এটি সাধারণ ক্ষেত্রে প্রাসঙ্গিক নয়, তবে বিশেষত লগিংয়ের জন্য, লগব্যাকের (মূল লোগোজে লেখক দ্বারা লিখিত) একধরণের প্যারামিটারাইজড লগিং রয়েছে যা এই সঠিক সমস্যার সমাধান করে - লগব্যাক.কোস.ইচ
ম্যাট প্যাসেল

উত্তর:


122

আমি পরীক্ষা করার জন্য একটি ছোট ক্লাস লিখেছিলাম যার দুটিতে আরও ভাল পারফরম্যান্স রয়েছে এবং + বিন্যাসের আগে চলে আসে। 5 থেকে 6 এর একটি ফ্যাক্টর দ্বারা এটি নিজের চেষ্টা করুন

import java.io.*;
import java.util.Date;

public class StringTest{

    public static void main( String[] args ){
    int i = 0;
    long prev_time = System.currentTimeMillis();
    long time;

    for( i = 0; i< 100000; i++){
        String s = "Blah" + i + "Blah";
    }
    time = System.currentTimeMillis() - prev_time;

    System.out.println("Time after for loop " + time);

    prev_time = System.currentTimeMillis();
    for( i = 0; i<100000; i++){
        String s = String.format("Blah %d Blah", i);
    }
    time = System.currentTimeMillis() - prev_time;
    System.out.println("Time after for loop " + time);

    }
}

বিভিন্ন এন এর জন্য উপরোক্ত চালনাটি দেখায় যে উভয়ই রৈখিক আচরণ করে, তবে String.format5-30 গুণ বেশি ধীর হয়।

কারণটি হ'ল বর্তমান বাস্তবায়নে String.formatপ্রথমে নিয়মিত অভিব্যক্তিগুলির সাথে ইনপুটটিকে পার্স করা হয় এবং তারপরে পরামিতিগুলি পূরণ করা হয়। অন্যদিকে, প্লাস দিয়ে কনকনাটেশন জাভাক (জেআইটি দ্বারা নয়) দ্বারা অনুকূলিত হয় এবং StringBuilder.appendসরাসরি ব্যবহার করে।

রানটাইম তুলনা


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

9
স্ট্রিংফুফার সম্পর্কে + পদ নিয়ে আরও একটি প্রশ্ন ছিল, জাভা এর সাম্প্রতিক সংস্করণগুলিতে স্ট্রিংবুফারের সাথে প্রতিস্থাপন করা হয়েছিল যখন সম্ভব তখন পারফরম্যান্সটি আলাদা না হয়
হাফেজ

25
এটি দেখতে অনেকটা মাইক্রোব্যাঙ্কমার্কের মতো যা খুব অপব্যবহারযোগ্য উপায়ে অপ্টিমাইজড হতে চলেছে।
ডেভিড এইচ। ক্লিমেটস

20
আরেকটি খারাপভাবে প্রয়োগ করা মাইক্রো-বেঞ্চমার্ক। উভয় পদ্ধতি কীভাবে আকারের আদেশ অনুসারে স্কেল করে। 100, 1000, 10000, 1000000, অপারেশনগুলি কীভাবে ব্যবহার করবেন। যদি আপনি কেবলমাত্র একটি পরীক্ষা চালান, মাত্রার এক ক্রমে, কোনও অ্যাপ্লিকেশন যা কোনও বিচ্ছিন্ন মূলরে চলছে না; কনটেক্সট স্যুইচিং, পটভূমি প্রক্রিয়া ইত্যাদির কারণে পার্থক্যটির কতটা পার্শ্ব-প্রতিক্রিয়া হিসাবে লেখা যায় তা বলার উপায় নেই
ইভান প্লেস

8
তবুও আপনি কখনই প্রধান জেআইটি থেকে বের হন না kick লাথি মারতে পারে না
জান জাইকা

241

আমি হাফেজ কোড নিয়েছি এবং একটি মেমরি পরীক্ষা যুক্ত করেছি :

private static void test() {
    Runtime runtime = Runtime.getRuntime();
    long memory;
    ...
    memory = runtime.freeMemory();
    // for loop code
    memory = memory-runtime.freeMemory();

আমি এটি প্রতিটি পদ্ধতির জন্য আলাদাভাবে চালিত করি, '+' অপারেটর, স্ট্রিং.ফর্ম্যাট এবং স্ট্রিংবিল্ডার (কলিং টু স্ট্রিং ()), যাতে ব্যবহৃত স্মৃতি অন্য পদ্ধতির দ্বারা প্রভাবিত হবে না। আমি আরও বক্তৃতা যুক্ত করেছি, "ব্লাহ" + i + "ব্লাহ" + আই + "ব্লাহ" + আই + "ব্লাহ" হিসাবে স্ট্রিং তৈরি করেছি।

ফলাফল নিম্নলিখিত হিসাবে রয়েছে (প্রতিটি গড়ে 5 রান):
অ্যাপ্রোচ টাইম (এমএস) মেমরি বরাদ্দ (দীর্ঘ)
'+' অপারেটর 747 320,504
স্ট্রিং.ফর্ম্যাট 16484 373,312
স্ট্রিংবিল্ডার 769 57,344

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

এবং একটি নোট, বিটিডাব্লু, বার্তাটি তৈরির আগে লগিং স্তরটি পরীক্ষা করতে ভুলবেন না ।

উপসংহার:

  1. আমি স্ট্রিংবিল্ডার ব্যবহার চালিয়ে যাব।
  2. আমার খুব বেশি সময় বা খুব কম জীবন আছে।

8
"বার্তাটি তৈরি করার আগে লগিং স্তরটি পরীক্ষা করতে ভুলবেন না", এটি একটি ভাল পরামর্শ, এটি কমপক্ষে ডিবাগ বার্তাগুলির জন্য করা উচিত, কারণ তাদের অনেক কিছুই থাকতে পারে এবং তারা উত্পাদন সক্রিয় না করা উচিত।
stivlo

39
না, এটি ঠিক নয়। ভোঁতা হওয়ার জন্য দুঃখিত তবে এটি যে আকর্ষণ করেছে তার সংখ্যা উদ্বেগজনক কিছু নয় of +অপারেটরটি ব্যবহার করে সমমানের StringBuilderকোডটি সংকলিত হয় । এর মতো মাইক্রোব্যাঙ্কমার্কগুলি পারফরম্যান্স পরিমাপ করার একটি ভাল উপায় নয় - কেন jvisualvm ব্যবহার করবেন না, এটি কোনও কারণে jdk এ রয়েছে। ধীর String.format() হবে , তবে কোনও অবজেক্ট বরাদ্দের চেয়ে ফর্ম্যাট স্ট্রিংকে পার্স করার সময় কারণে। লগিং শৈল্পিকগুলি তৈরির বিষয়ে উল্লেখ করা যতক্ষণ না আপনি নিশ্চিত হন যে তাদের প্রয়োজনীয় প্রয়োজন তা ভাল পরামর্শ, তবে যদি এটির কোনও পারফরম্যান্স প্রভাব পড়ে তবে এটি ভুল জায়গায় রয়েছে।
কার্টেনডগ

1
@ কার্টেনডগ, আপনার মন্তব্যটি চার বছরের পুরানো পোস্টে করা হয়েছিল, আপনি কি ডকুমেন্টেশনের দিকে ইঙ্গিত করতে পারেন বা পার্থক্যটি সমাধান করার জন্য একটি পৃথক উত্তর তৈরি করতে পারেন?
কুর্তজবট

1
: এর @ CurtainDog এর মন্তব্য সমর্থনে রেফারেন্স stackoverflow.com/a/1532499/2872712 । এটি, লুপটি না করা হলে + পছন্দ করা হয়।
এপ্রিকট

And a note, BTW, don't forget to check the logging level before constructing the message.ভাল পরামর্শ নয়। ধরে নিই আমরা java.util.logging.*বিশেষভাবে কথা বলছি , লগিং স্তরটি পরীক্ষা করা যখন আপনি উন্নত প্রসেসিংয়ের কথা বলছেন যা কোনও প্রোগ্রামে বিরূপ প্রভাব ফেলবে যা আপনি চাইবেন না যখন কোনও প্রোগ্রামে লগিং উপযুক্ত স্তরে চালু না হয়। স্ট্রিং ফর্ম্যাটিং সমস্ত ধরণের প্রক্রিয়াকরণ এ জাতীয় নয়। java.util.loggingফর্ম্যাট করা ফ্রেমওয়ার্কের অংশ , এবং ফর্ম্যাটরটি শুরু হওয়ার আগে লগার নিজেই লগিং স্তরটি পরীক্ষা করে।
সার্চেইনগাইন 27

30

এখানে উপস্থাপিত সমস্ত মানদণ্ডের কিছু ত্রুটি রয়েছে , সুতরাং ফলাফলগুলি নির্ভরযোগ্য নয়।

আমি অবাক হয়েছি যে কেউ জেএমএইচ বেঞ্চমার্কিংয়ের জন্য ব্যবহার করেনি , তাই আমিও করেছি।

ফলাফল:

Benchmark             Mode  Cnt     Score     Error  Units
MyBenchmark.testOld  thrpt   20  9645.834 ± 238.165  ops/s  // using +
MyBenchmark.testNew  thrpt   20   429.898 ±  10.551  ops/s  // using String.format

ইউনিটগুলি প্রতি সেকেন্ডে অপারেশন হয়, আরও ভাল। বেঞ্চমার্ক উত্স কোড । ওপেনজেডিকে আইসডটিয়া 2.5.4 জাভা ভার্চুয়াল মেশিন ব্যবহার করা হয়েছিল।

সুতরাং, পুরানো শৈলী (ব্যবহার +) অনেক দ্রুত।


5
কোনটি "+" এবং কোনটি "ফর্ম্যাট" ছিল তা যদি আপনি উল্লেখ করেন তবে এটি ব্যাখ্যা করা আরও সহজ হবে।
অজাহানচার্লস

21

আপনার পুরানো কুরুচিপূর্ণ শৈলীটি JAVAC 1.6 দ্বারা স্বয়ংক্রিয়ভাবে সংকলিত হয়েছে:

StringBuilder sb = new StringBuilder("What do you get if you multiply ");
sb.append(varSix);
sb.append(" by ");
sb.append(varNine);
sb.append("?");
String s =  sb.toString();

সুতরাং এর সাথে এবং স্ট্রিংবিল্ডার ব্যবহারের মধ্যে একেবারেই কোনও পার্থক্য নেই।

স্ট্রিং.ফর্ম্যাটটি অনেক বেশি ভারী ওজনযুক্ত কারণ এটি একটি নতুন ফর্ম্যাটর তৈরি করে, আপনার ইনপুট বিন্যাসের স্ট্রিংটিকে পার্স করে, একটি স্ট্রিংবিল্ডার তৈরি করে, এতে সবকিছু সংযোজন করে এবং স্ট্রিং () এ কল করে।


পঠনযোগ্যতার নিরিখে, আপনার পোস্ট করা কোডটি স্ট্রিং.ফর্ম্যাটের চেয়ে অনেক বেশি জটিল ("যদি আপনি% d কে% d দ্বারা গুণিত করেন তবে আপনি কী পাবেন?", ভারসিক্স, ভার্নাইন);
সন্ধ্যাশ্রেণী

12
+এবং StringBuilderসত্যিকারের মধ্যে কোনও পার্থক্য নেই । দুর্ভাগ্যক্রমে এই থ্রেডের অন্যান্য উত্তরে অনেক ভুল তথ্য রয়েছে। আমি প্রশ্নটি পরিবর্তন করতে প্রায় প্রলোভিত how should I not be measuring performance
কার্টেনডগ

12

জাভা এর স্ট্রিং.ফর্ম্যাট এর মত কাজ করে:

  1. এটি বিন্যাসের স্ট্রিংটিকে বিশ্লেষণ করে ফর্ম্যাট খণ্ডের তালিকায় বিস্ফোরিত হয়
  2. এটি স্ট্রিংবিল্ডারে রূপান্তর করে ফর্ম্যাট খণ্ডগুলিকে পুনরুক্তি করে, যা মূলত একটি অ্যারে যা প্রয়োজন অনুযায়ী নিজেকে নতুন আকারে অনুলিপি করে পুনরায় আকার দেয়। এটি প্রয়োজনীয় কারণ আমরা এখনও চূড়ান্ত স্ট্রিং বরাদ্দ করতে জানি না
  3. স্ট্রিংবিল্ডার.টোস্ট্রিং () তার অভ্যন্তরীণ বাফারটিকে একটি নতুন স্ট্রিংয়ে অনুলিপি করে

যদি এই ডেটার জন্য চূড়ান্ত গন্তব্যটি একটি স্ট্রিম হয় (যেমন কোনও ওয়েবপৃষ্ঠায় রেকর্ডিং বা কোনও ফাইলে লেখার জন্য), আপনি সরাসরি আপনার স্ট্রিমের খণ্ডগুলিকে একত্রিত করতে পারেন:

new PrintStream(outputStream, autoFlush, encoding).format("hello {0}", "world");

আমি অনুমান করি যে অপটিমাইজারটি ফর্ম্যাট স্ট্রিং প্রসেসিংটি অপ্টিমাইজ করবে। যদি তাই হয়, আপনি সমতুল্য অবশিষ্ট করছি amortized নিজে একটি StringBuilder আপনার String.format unrolling করতে কর্মক্ষমতা।


5
আমি মনে করি না ফর্ম্যাট স্ট্রিং প্রসেসিংয়ের অপ্টিমাইজেশন সম্পর্কে আপনার জল্পনা সঠিক correct জাভা using ব্যবহার করে কিছু বাস্তব-জগতের পরীক্ষাগুলিতে আমি দেখতে পেয়েছি যে String.formatঅভ্যন্তরীণ লুপগুলিতে (কয়েক মিলিয়ন বার চালানো) ব্যবহারের ফলে আমার মৃত্যুদন্ড কার্যকর করার সময় 10% এরও বেশি সময় ব্যয় হয়েছিল java.util.Formatter.parse(String)। এটি ইঙ্গিত দেয় যে অভ্যন্তরীণ লুপগুলিতে, আপনাকে কল করা Formatter.formatবা এটিকে যে কোনও কিছু বলা উচিত সেগুলি এড়িয়ে চলা উচিত including PrintStream.format(জাভা স্ট্যান্ডার্ড লিব, আইএমও-এর একটি ত্রুটি বিশেষত যেহেতু আপনি পার্সড ফর্ম্যাট স্ট্রিংটি ক্যাশে করতে পারবেন না)।
অ্যান্ডি ম্যাককিনলে

8

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

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


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

6

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

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

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

String getSmallString() {
  String largeString = // load from file; say 2M in size
  return largeString.substring(100, 300);
}

সেই বৃহত স্ট্রিংটি এখনও মেমোরিতে রয়েছে কারণ জাভা সাবস্ট্রিংগুলি ঠিক সেভাবেই কাজ করে। আরও ভাল সংস্করণটি হ'ল:

  return new String(largeString.substring(100, 300));

অথবা

  return String.format("%s", largeString.substring(100, 300));

দ্বিতীয় ফর্মটি সম্ভবত আরও কার্যকর যদি আপনি একই সাথে অন্যান্য জিনিসগুলি করেন useful


8
"সম্পর্কিত প্রশ্ন" দেখানোর উপযুক্ত আসলে সি # এবং তাই প্রযোজ্য নয়।
এয়ার

আপনি কোন সরঞ্জামটি মেমরি বিভাজন পরিমাপ করতে ব্যবহার করেছেন এবং টুকরো টুকরো টুকরো এমনকি ম্যামের জন্য একটি গতির পার্থক্য করে?
kritzikratzi

এটি উল্লেখ করার মতো যে জাভা 7 + থেকে সাবস্ট্রিং পদ্ধতিটি পরিবর্তন করা হয়েছিল। এটিতে এখন কেবল নতুন স্ট্রিং প্রতিনিধিত্ব করা উচিত যা কেবল সংক্ষিপ্ত অক্ষরগুলিতে রয়েছে। তার মানে যে স্ট্রিং :: নতুন ফেরত দেওয়ার দরকার নেই: নতুন
জোয়াও রেবেলো

5

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

এখন যদি আপনি কখনই কোনও কিছুর অনুবাদ করার পরিকল্পনা করেন না, তবে হয় হয় + অপারেটরগুলিকে রূপান্তর করে জাভায় নির্মিত StringBuilder। বা জাভা StringBuilderস্পষ্টভাবে ব্যবহার করুন ।


3

শুধুমাত্র লগিং পয়েন্ট থেকে অন্য দৃষ্টিকোণ।

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

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

আপনি লগ ইন করতে না চাইলে সত্যই কনক্যাট / ফর্ম্যাট করার দরকার নেই। আমি যদি এর মতো কোনও পদ্ধতি সংজ্ঞায়িত করি তবে বলি

public void logDebug(String... args, Throwable t) {
    if(debugOn) {
       // call concat methods for all args
       //log the final debug message
    }
}

এই পদ্ধতির মধ্যে ক্যানক্যাট / ফর্ম্যাটারটি আসলেই ডাকা হয় না যদি এটির কোনও ডিবাগ বার্তা এবং ডিবাগঅন = মিথ্যা

যদিও এখানে ফরম্যাটারের পরিবর্তে স্ট্রিংবিল্ডার ব্যবহার করা আরও ভাল। এর মূল প্রেরণা হ'ল যে কোনওটি এড়ানো।

একই সময়ে আমি প্রতিটি লগিং স্টেটমেন্টের জন্য "if" ব্লক যুক্ত করা পছন্দ করি না

  • এটি পঠনযোগ্যতা প্রভাবিত করে
  • আমার ইউনিট পরীক্ষাগুলিতে কভারেজ হ্রাস করে - আপনি যখন প্রতিটি লাইন পরীক্ষা করা হয়েছে তা নিশ্চিত করতে চান তখন বিভ্রান্তি হয়।

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


আপনি কি slf4j-api এর মতো কোনও বিদ্যমান লাইব্রেরিটি প্যাকেজ করতে পারেন যা তাদের প্যারামিটারাইজড লগিং বৈশিষ্ট্যটির সাহায্যে এই ইউসকেসটিকে সম্বোধন করতে পারে? slf4j.org/faq.html#logging_performance
ammianus

2

আমি স্ট্রিংবুডারকে অন্তর্ভুক্ত করার জন্য কেবল হাফেজের পরীক্ষাটি সংশোধন করেছি। স্ট্রিংবিল্ডার এক্সপি-তে jdk 1.6.0_10 ক্লায়েন্ট ব্যবহার করে স্ট্রিং.ফর্ম্যাটের চেয়ে 33 গুণ বেশি গতিযুক্ত। -সার্ভার স্যুইচ ব্যবহার করে গুণককে 20 এ কমিয়ে দেয়।

public class StringTest {

   public static void main( String[] args ) {
      test();
      test();
   }

   private static void test() {
      int i = 0;
      long prev_time = System.currentTimeMillis();
      long time;

      for ( i = 0; i < 1000000; i++ ) {
         String s = "Blah" + i + "Blah";
      }
      time = System.currentTimeMillis() - prev_time;

      System.out.println("Time after for loop " + time);

      prev_time = System.currentTimeMillis();
      for ( i = 0; i < 1000000; i++ ) {
         String s = String.format("Blah %d Blah", i);
      }
      time = System.currentTimeMillis() - prev_time;
      System.out.println("Time after for loop " + time);

      prev_time = System.currentTimeMillis();
      for ( i = 0; i < 1000000; i++ ) {
         new StringBuilder("Blah").append(i).append("Blah");
      }
      time = System.currentTimeMillis() - prev_time;
      System.out.println("Time after for loop " + time);
   }
}

যদিও এটি তীব্র শোনায়, আমি এটিকে কেবল বিরল ক্ষেত্রেই প্রাসঙ্গিক বলে মনে করি, কারণ নিখুঁত সংখ্যাগুলি খুব কম: 1 মিলিয়ন সাধারণ স্ট্রিং.ফর্ম্যাট কলগুলির জন্য 4 এস যথাযথ - যতক্ষণ না আমি লগিংয়ের জন্য তাদের ব্যবহার করি বা মত।

আপডেট: মন্তব্যগুলিতে sjbotha দ্বারা নির্দেশিত হিসাবে, স্ট্রিংবিল্ডার পরীক্ষাটি অবৈধ, যেহেতু এটি একটি ফাইনাল অনুপস্থিত .toString()

থেকে সঠিক গতি-আপ ফ্যাক্টর String.format(.)থেকে StringBuilder23 আমার মেশিন (সঙ্গে 16 হয় -serverসুইচ)।


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

আমি এটি করেছি, লুপের জন্য 0 এমএস লাগে। এমনকি যদি এটি সময় নেয় তবে এটি কেবল কারণকে বাড়িয়ে তুলবে।
the.duckman

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

1

এখানে হাফেজ প্রবেশের পরিবর্তিত সংস্করণ রয়েছে। এটিতে একটি স্ট্রিং বিল্ডার বিকল্প অন্তর্ভুক্ত।

public class BLA
{
public static final String BLAH = "Blah ";
public static final String BLAH2 = " Blah";
public static final String BLAH3 = "Blah %d Blah";


public static void main(String[] args) {
    int i = 0;
    long prev_time = System.currentTimeMillis();
    long time;
    int numLoops = 1000000;

    for( i = 0; i< numLoops; i++){
        String s = BLAH + i + BLAH2;
    }
    time = System.currentTimeMillis() - prev_time;

    System.out.println("Time after for loop " + time);

    prev_time = System.currentTimeMillis();
    for( i = 0; i<numLoops; i++){
        String s = String.format(BLAH3, i);
    }
    time = System.currentTimeMillis() - prev_time;
    System.out.println("Time after for loop " + time);

    prev_time = System.currentTimeMillis();
    for( i = 0; i<numLoops; i++){
        StringBuilder sb = new StringBuilder();
        sb.append(BLAH);
        sb.append(i);
        sb.append(BLAH2);
        String s = sb.toString();
    }
    time = System.currentTimeMillis() - prev_time;
    System.out.println("Time after for loop " + time);

}

}

লুপের পরে সময় 391 লুপের পরে সময় 4163 লুপের পরে সময় 227


0

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

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


1
দ্বিতীয় উদাহরণের বাইটকোডটি অবশ্যই স্ট্রিং.ফর্ম্যাটকে কল করে তবে আমি যদি সাধারণ কোন কনটেন্টেশন না করে তবে আমি আতঙ্কিত হয়ে যাব। সংকলক কেন এমন ফর্ম্যাট স্ট্রিং ব্যবহার করবে যা তারপরে পার্স করতে হবে?
জন স্কিটি

আমি "বাইকোড" ব্যবহার করেছি যেখানে আমার "বাইনারি কোড" বলা উচিত ছিল। এটি যখন সমস্ত জম্পাস এবং মুভিগুলিতে নেমে আসে তখন এটি ঠিক একই কোড হতে পারে।
হ্যাঁ - যে জ্যাক

0

সংক্ষেপে "hello".concat( "world!" )স্বল্প সংখ্যক স্ট্রিংয়ের জন্য ব্যবহার বিবেচনা করুন । এটি অন্যান্য পদ্ধতির চেয়ে পারফরম্যান্সের জন্য আরও ভাল হতে পারে।

স্ট্রিংবিল্ডার বা কেবল স্ট্রিং ব্যবহার করার চেয়ে আপনি যদি স্ট্রিংবিল্ডার ব্যবহারের কথা বিবেচনা করেন তবে তার চেয়ে 3 টির বেশি স্ট্রিং থাকে that

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