স্ট্রিং সংমিশ্রণ অ্যারে যোগদানের চেয়ে দ্রুত কেন?


114

আজ, আমি স্ট্রিং সংমিশ্রণের গতি সম্পর্কে এই থ্রেডটি পড়েছি ।

আশ্চর্যের বিষয় হল, স্ট্রিং কনটেন্টেশনটি বিজয়ী ছিল:

http://jsben.ch/#/OJ3vo

ফলাফল আমি যা ভেবেছিলাম তার বিপরীতে ছিল। এ ছাড়া এ ব্যাপারে অনেক নিবন্ধ যা মত এবং বিপরীতক্রমে ব্যাখ্যা হয় এই

আমি অনুমান করতে পারি যে ব্রাউজারগুলি concatসর্বশেষতম সংস্করণে স্ট্রিং করতে অনুকূলিত হয়েছে , তবে তারা কীভাবে তা করে? আমরা কি বলতে পারি যে +স্ট্রিংগুলি সংযুক্ত করার সময় এটি ব্যবহার করা ভাল ?


হালনাগাদ

সুতরাং, আধুনিক ব্রাউজারে স্ট্রিং সংযুক্তকরণের অপ্টিমাইজ তাই ব্যবহার করছে +লক্ষণ ব্যবহার চেয়ে দ্রুত joinযখন আপনি করতে চান CONCATENATE স্ট্রিং।

তবে @ আর্থার উল্লেখ করেছেন যে joinআপনি যদি কোনও বিচ্ছেদের সাথে স্ট্রিংগুলিতে আসলে যোগ দিতে চান তবে এটি দ্রুত is


আপডেট - 2020
ক্রোম: অ্যারে joinপ্রায় 2 times fasterস্ট্রিং কনক্যাট + দেখুন: https://stackoverflow.com/a/54970240/984471

একটি নোট হিসাবে:

  • অ্যারে থাকলে joinভাল হয়large strings
  • যদি আমাদের several small stringsচূড়ান্ত আউটপুট জেনারেট করতে হয় তবে স্ট্রিং কনক্যাট নিয়ে যাওয়া ভাল +, অন্যথায় অ্যারের সাথে যাওয়ার জন্য শেষে বেশ কয়েকটি অ্যারে স্ট্রিং রূপান্তর প্রয়োজন যা পারফরম্যান্স ওভারলোড।


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

উত্তর:


149

ব্রাউজারের স্ট্রিং অপ্টিমাইজেশানগুলি স্ট্রিং উপসংগঠনের চিত্রকে পরিবর্তন করেছে।

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

- দক্ষ জাভাস্ক্রিপ্ট রচনা: অধ্যায় 7 - এমনকি দ্রুততর ওয়েবসাইটগুলি

ভি 8 জাভাস্ক্রিপ্ট ইঞ্জিন (গুগল ক্রোমে ব্যবহৃত) স্ট্রিং কনটেন্টেশন করার জন্য এই কোডটি ব্যবহার করে :

// ECMA-262, section 15.5.4.6
function StringConcat() {
  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
    throw MakeTypeError("called_on_null_or_undefined", ["String.prototype.concat"]);
  }
  var len = %_ArgumentsLength();
  var this_as_string = TO_STRING_INLINE(this);
  if (len === 1) {
    return this_as_string + %_Arguments(0);
  }
  var parts = new InternalArray(len + 1);
  parts[0] = this_as_string;
  for (var i = 0; i < len; i++) {
    var part = %_Arguments(i);
    parts[i + 1] = TO_STRING_INLINE(part);
  }
  return %StringBuilderConcat(parts, len + 1, "");
}

সুতরাং, অভ্যন্তরীণভাবে তারা এটি অভ্যন্তরীণ অ্যারে ( partsভেরিয়েবল) তৈরি করে এটি অনুকূলিত করে , যা পরে পূর্ণ হয়। এই অংশগুলির সাথে স্ট্রিংবিল্ডার কনক্যাট ফাংশনটি ডাকা হয়। এটি দ্রুত কারণ স্ট্রিংবিল্ডার কনক্যাট ফাংশনটি বেশ কয়েকটি ভারী অনুকূলিত সি ++ কোড। এখানে উদ্ধৃতি দেওয়া খুব দীর্ঘ, তবে কোডটিRUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) দেখার জন্য রানটাইম.সি.সি. ফাইলে অনুসন্ধান করুন ।


4
আপনি সত্যিই আকর্ষণীয় জিনিসটি রেখে গেছেন, অ্যারেটি কেবল বিভিন্ন আর্গুমেন্ট গণনা সহ রানটাইম_সট্রিংবিল্ডার কনক্যাট কল করতে ব্যবহৃত হয়। তবে আসল কাজটি সেখানেই হয়।
অশুভপি

41
অপ্টিমাইজেশন 101: আপনার লক্ষ্যটি কমপক্ষে ধীর হওয়া উচিত! উদাহরণস্বরূপ, arr.join vs str+ক্রোমে আপনি পাবেন (প্রতি সেকেন্ডের ক্রিয়াকলাপে) 25k/s vs 52k/s। ফায়ারফক্সে নতুন আপনি পাবেন 76k/s vs 212k/s। তাই str+দ্রুততর। তবে অন্য ব্রাউজারগুলি দেখতে দিন। অপেরা 43k / s বনাম 26k / s দেয়। আইই দেয় 1300/s vs 1002/s। দেখুন কি হয়? শুধুমাত্র ব্রাউজার যা করার প্রয়োজন অপ্টিমাইজেশান ব্যবহার কি সব অন্যদের, যেখানে এটি ব্যাপার এ সব করে না মন্থর ভালো হবে। সুতরাং, এই নিবন্ধগুলির কিছুই পারফরম্যান্স সম্পর্কে কিছুই বুঝতে পারে না।
gcb

45
@gcb, শুধুমাত্র ব্রাউজারগুলির জন্য যোগদানের কাজগুলি দ্রুত করা উচিত নয়। আমার 95% ব্যবহারকারীর এফএফ এবং ক্রোম রয়েছে। আমি 95% ব্যবহারের ক্ষেত্রে অনুকূল করতে চলেছি।
পল ড্রপার

7
@ পলড্রাপার যদি 90% ব্যবহারকারী দ্রুত ব্রাউজারে থাকেন এবং যে কোনও বিকল্প আপনি পছন্দ করেন সেগুলি তাদের 0.001s অর্জন করবে, তবে আপনি যদি 0.001 এর মধ্যে অন্য ব্যবহারকারীদের দণ্ডিত করতে চান তবে আপনার 10% ব্যবহারকারী 2s লাভ করবেন ... সিদ্ধান্ত স্পষ্ট. যদি আপনি এটি দেখতে না পান তবে আপনি যার জন্য কোড করেন তার জন্য আমি দুঃখিত।
gcb

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

23

ফায়ারফক্স দ্রুত কারণ এটি রোপস ( দড়ি: একটি বিকল্পের স্ট্রিংস ) নামে কিছু ব্যবহার করে । একটি দড়ি মূলত কেবল একটি ডিএজি, যেখানে প্রতিটি নোড একটি স্ট্রিং থাকে।

উদাহরণস্বরূপ, আপনি যদি a = 'abc'.concat('def')এটি করেন তবে সদ্য তৈরি হওয়া অবজেক্টটি এর মতো দেখবে। অবশ্যই এটি মেমরির মতো দেখতে হুবহু নয়, কারণ আপনার স্ট্রিং টাইপ, দৈর্ঘ্য এবং সম্ভবত অন্য কোনও ক্ষেত্রে একটি ক্ষেত্র থাকা দরকার।

a = {
 nodeA: 'abc',
 nodeB: 'def'
}

এবং b = a.concat('123')

b = {
  nodeA: a, /* {
             nodeA: 'abc',
             nodeB: 'def'
          } */
  nodeB: '123'
}           

তাই সাধারণ ক্ষেত্রে ভিএমকে প্রায় কোনও কাজ করতে হয় না। একমাত্র সমস্যা হ'ল ফলস্বরূপ স্ট্রিংটিতে এটি অন্য ক্রিয়াকলাপটি কিছুটা কমিয়ে দেয়। এছাড়াও এটি অবশ্যই মেমরির ওভারহেড হ্রাস করে।

অন্যদিকে ['abc', 'def'].join('')মেমরিতে নতুন স্ট্রিং ফ্ল্যাটটি রাখার জন্য সাধারণত কেবল মেমরি বরাদ্দ করা হত। (সম্ভবত এটি অনুকূলিত করা উচিত)


6

আমি জানি এটি একটি পুরানো থ্রেড তবে আপনার পরীক্ষাটি ভুল। আপনি output += myarray[i];যখন যাচ্ছিলেন তখন এটি আরও বেশি হওয়া উচিত output += "" + myarray[i];কারণ আপনি ভুলে গেছেন, আপনাকে কোনও কিছুর সাথে আইটেমগুলি একসাথে রাখতে হবে। কনক্যাট কোডটি এমন কিছু হওয়া উচিত:

var output = myarray[0];
for (var i = 1, len = myarray.length; i<len; i++){
    output += "" + myarray[i];
}

এইভাবে, একসাথে আঠালো উপাদানগুলির কারণে আপনি একের পরিবর্তে দুটি ক্রিয়াকলাপ করছেন।

Array.join() দ্রুততর.


আমি আপনার উত্তর পাই না। "" +মূল এবং আসল মধ্যে পার্থক্য কি ?
সঙ্ঘুন লী

এটি প্রতিটি পুনরাবৃত্তির একটির পরিবর্তে দুটি ক্রিয়াকলাপ যা আরও সময় নেয়।
আর্থার

1
এবং কেন আমাদের এটি রাখা প্রয়োজন? আমরা ইতিমধ্যে outputএটি ছাড়াই আইটেম আঠালো করছি।
সংঘুন লী

কারণ এভাবেই কাজ করে যোগদান join উদাহরণস্বরূপ, আপনি এমনটিও করতে পারেন Array.join(",")যা আপনার forলুপের সাথে কাজ করবে না
আর্থার

ওহ আমি পেয়েছি। যোগদান () দ্রুত হয় কিনা তা আপনি ইতিমধ্যে পরীক্ষা করেছেন?
সঙ্ঘুন লি লি

5

বিপুল পরিমাণে ডেটা যোগ করার জন্য দ্রুত হয়, সুতরাং প্রশ্নটি ভুলভাবে বলা হয়েছে।

let result = "";
let startTime = new Date().getTime();
for (let i = 0; i < 2000000; i++) {
    result += "x";
}
console.log("concatenation time: " + (new Date().getTime() - startTime));

startTime = new Date().getTime();
let array = new Array(2000000);
for (let i = 0; i < 2000000; i++) {
    array[i] = "x";
}
result = array.join("");
console.log("join time: " + (new Date().getTime() - startTime));

ক্রোম 72.0.3626.119, ফায়ারফক্স 65.0.1, এজ 42.17134.1.0 এ পরীক্ষিত। মনে রাখবেন যে অ্যারে তৈরির অন্তর্ভুক্ত থাকা সত্ত্বেও এটি আরও দ্রুত!


~ আগস্ট 2020. সত্য। ক্রোমে: অ্যারে যোগদানের সময়: 462. স্ট্রিং কনক্যাট (+) সময়: 827. যোগদান প্রায় 2 গুণ দ্রুত হয়।
মনোহর রেড্ডি পোরেড্ডি

3

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

অ্যারে.জাইন এফটিডব্লিউ!


2

আমি বলব যে স্ট্রিংগুলির সাহায্যে আরও বড় বাফারটিকে পূর্বনির্ধারণ করা আরও সহজ। প্রতিটি উপাদান মাত্র 2 বাইট (যদি ইউনিকোড হয়), তাই আপনি রক্ষণশীল হলেও, আপনি স্ট্রিংয়ের জন্য একটি দুর্দান্ত বড় বাফারকে পূর্বনির্ধারণ করতে পারেন। সঙ্গে arraysপ্রতিটি উপাদান, কারণ প্রতিটি উপাদান একটি হল আরো "জটিল" হয় Object, তাই একটি রক্ষণশীল বাস্তবায়ন কম উপাদানের জন্য স্থান preallocate হবে।

আপনি যদি for(j=0;j<1000;j++)প্রতিটিটির আগে একটি যুক্ত করার চেষ্টা করেন forআপনি দেখতে পাবেন যে (ক্রোমের অধীনে) গতির পার্থক্য আরও কম হবে। শেষ পর্যন্ত এটি স্ট্রিং কনটেনটেশনের জন্য এখনও 1.5x ছিল তবে এটি আগের তুলনায় ২. than এর চেয়ে ছোট ছিল।

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

জেনে থাকুন যে জেএস ইঞ্জিনগুলির অনেকগুলি বাস্তবায়নের একক ধরণের অ্যারেগুলির জন্য একটি অপ্টিমাইজেশন রয়েছে যা আমার লেখা সমস্ত অকেজো করে ফেলবে :-)


1

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


0

এটি স্পষ্টভাবে জাভাস্ক্রিপ্ট ইঞ্জিন বাস্তবায়নের উপর নির্ভর করে। এমনকি একটি ইঞ্জিনের বিভিন্ন সংস্করণের জন্যও আপনি আলাদা আলাদা ফলাফল পেতে পারেন results এটি যাচাই করার জন্য আপনার নিজের মানদণ্ড করা উচিত।

আমি বলব যে String.concatভি 8 এর সাম্প্রতিক সংস্করণগুলিতে আরও ভাল পারফরম্যান্স রয়েছে। তবে ফায়ারফক্স এবং অপেরার জন্য, Array.joinএটি একটি বিজয়ী।


-1

আমার ধারণাটি হ'ল, যখন প্রতিটি সংস্করণ অনেকগুলি কনটেন্টেশনের ব্যয় করে, যোগদানের সংস্করণগুলি সেগুলি ছাড়াও অ্যারে তৈরি করে।

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