যুক্তি তালিকাগুলি ব্যবহার করে বাশের পারফরম্যান্সে সমস্যা আছে?


11

বাশ 5.0 এ সমাধান করা হয়েছে

পটভূমি

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

ধরুন আপনি ইউনিকোড অক্ষরের তালিকার জন্য কয়েকটি শেল পরীক্ষা করছেন:

printf "$(printf '\\U%x ' {33..200})"

এবং সেখানে আরও প্রায় 1 মিলিয়ন ইউনিকোড অক্ষর রয়েছে, 20.000 এর মধ্যে পরীক্ষা হচ্ছে এটি খুব বেশি বলে মনে হচ্ছে না।
এছাড়াও ধরে নিন যে আপনি অবস্থানগুলি আর্গুমেন্ট হিসাবে সেট করেছেন:

set -- $(printf "$(printf '\\U%x ' {33..20000})")

প্রতিটি ফাংশনে চরিত্রগুলিকে বিভিন্ন উপায়ে প্রক্রিয়া করার উদ্দেশ্যে সুতরাং ফাংশনগুলির ফর্ম test1 "$@"বা অনুরূপ হওয়া উচিত । এখন আমি বুঝতে পারি যে এটি কীভাবে খারাপ ধারণা in

এখন ধরে নিন, কোনটি ভাল তা খুঁজে বের করার জন্য প্রতিটি সমাধানের সময়ের (একটি এন = 1000) প্রয়োজন রয়েছে, এইরকম পরিস্থিতিতে আপনি এর মতো কাঠামোর সাথে শেষ করবেন:

#!/bin/bash --
TIMEFORMAT='real: %R'  # '%R %U %S'

set -- $(printf "$(printf '\\U%x ' {33..20000})")
n=1000

test1(){ echo "$1"; } >/dev/null
test2(){ echo "$#"; } >/dev/null
test3(){ :; }

main1(){ time for i in $(seq $n); do test1 "$@"; done
         time for i in $(seq $n); do test2 "$@"; done
         time for i in $(seq $n); do test3 "$@"; done
       }

main1 "$@"

test#এখানে উপস্থাপন করার জন্য ফাংশনগুলি খুব সাধারণভাবে তৈরি করা হয়।
আসলগুলি আস্তে আস্তে ছাঁটাই হয়েছিল যেখানে খুঁজে পেতে বিশাল দেরি হয়েছিল।

উপরের স্ক্রিপ্টটি কাজ করে, আপনি এটি চালাতে পারেন এবং খুব সামান্য কিছু সময় ব্যয় করতে পারেন।

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

নিজেকে চেষ্টা করার জন্য, সমস্ত "$@"ফাংশনটি মুছে ফেলুন main1(বা একটি অনুলিপি তৈরি করুন) এবং আবার (বা উভয় main1এবং অনুলিপি main2(সাথে main2 "$@")) তুলনা করুন। এটি মূল পোস্টে (ওপি) নীচে নীচে বেসিক কাঠামো।

তবে আমি ভাবলাম: শেলটি "কিছুই করতে" কেন এত দিন নিচ্ছে? হ্যাঁ, শুধুমাত্র "কয়েক সেকেন্ড", তবে এখনও, কেন ?.

এটি আমাকে অন্যান্য শেলগুলিতে পরীক্ষা করার জন্য এটি আবিষ্কার করেছিল যে কেবল বাশের কাছেই এই সমস্যা ছিল। (উপরের মত একই স্ক্রিপ্ট)
চেষ্টা করুন ksh ./script

এটি এই বিবরণীর দিকে পরিচালিত করে: test#কোনও যুক্তি ছাড়াই একটি ফাংশন ( ) কল করা পিতা-মাতার মধ্যে যুক্তি দ্বারা বিলম্বিত হয় ( main#)। এটি নীচের নীচে মূল পোস্ট (ওপি) এর পরে নিম্নলিখিত বর্ণনাকারী ছিল।

আসল পোস্ট।

(ব্যাশ 4.4.12 (1) -release মধ্যে) একটি ফাংশন কল করা হচ্ছে কিছুই f1(){ :; }হাজার গুণ করা হয় তুলনায় ধীর :কিন্তু শুধুমাত্র যদি সংজ্ঞায়িত আর্গুমেন্ট পিতা বা মাতা ফাংশন কলিং, কেন?

#!/bin/bash
TIMEFORMAT='real: %R'

f1   () { :; }

f2   () {
   echo "                     args = $#";
   printf '1 function no   args yes '; time for ((i=1;i<$n;i++)); do  :   ; done 
   printf '2 function yes  args yes '; time for ((i=1;i<$n;i++)); do  f1  ; done
   set --
   printf '3 function yes  args no  '; time for ((i=1;i<$n;i++)); do  f1  ; done
   echo
        }

main1() { set -- $(seq $m)
          f2  ""
          f2 "$@"
        }

n=1000; m=20000; main1

এর ফলাফল test1:

                     args = 1
1 function no   args yes real:  0.013
2 function yes  args yes real:  0.024
3 function yes  args no  real:  0.020

                     args = 20000
1 function no   args yes real:  0.010
2 function yes  args yes real: 20.326
3 function yes  args no  real:  0.019

ফাংশনে কোনও যুক্তি বা ইনপুট বা আউটপুট ব্যবহৃত হয় না f1, হাজার (1000) এর একটি ফ্যাক্টরের বিলম্ব অপ্রত্যাশিত। 1


পরীক্ষাগুলি কয়েকটি শেলগুলিতে প্রসারিত করা, ফলাফলগুলি সামঞ্জস্যপূর্ণ, বেশিরভাগ শেলগুলির কোনও অসুবিধা হয় না বা বিলম্ব হয় না (একই এন এবং এম ব্যবহৃত হয়):

test2(){
          for sh in dash mksh ksh zsh bash b50sh
      do
          echo "$sh" >&2
#         \time -f '\t%E' seq "$m" >/dev/null
#         \time -f '\t%E' "$sh" -c 'set -- $(seq '"$m"'); for i do :; done'
          \time -f '\t%E' "$sh" -c 'f(){ :;}; while [ "$((i+=1))" -lt '"$n"' ]; do : ; done;' $(seq $m)
          \time -f '\t%E' "$sh" -c 'f(){ :;}; while [ "$((i+=1))" -lt '"$n"' ]; do f ; done;' $(seq $m)
      done
}

test2

ফলাফল:

dash
        0:00.01
        0:00.01
mksh
        0:00.01
        0:00.02
ksh
        0:00.01
        0:00.02
zsh
        0:00.02
        0:00.04
bash
        0:10.71
        0:30.03
b55sh             # --without-bash-malloc
        0:00.04
        0:17.11
b56sh             # RELSTATUS=release
        0:00.03
        0:15.47
b50sh             # Debug enabled (RELSTATUS=alpha)
        0:04.62
        xxxxxxx    More than a day ......

seqযুক্তি তালিকার কোনওটিই বা প্রক্রিয়াজাতকরণ বিলম্বের জন্য উত্স নয় তা নিশ্চিত করার জন্য অন্য দুটি পরীক্ষার অভিযোগ ছাড়াই কমেন্ট করুন ।

1 এটাজানা যায় আর্গুমেন্ট দ্বারা ফলাফল ক্ষণস্থায়ী সঞ্চালনের সময় বৃদ্ধি হবে। ধন্যবাদ@ এসএমএল


3
মেটা প্রভাব দ্বারা সংরক্ষিত। unix.meta.stackexchange.com/q/5021/3562
জোশুয়া

উত্তর:


9

অনুলিপি করা হয়েছে: লুপটিতে বিলম্ব কেন? আপনার অনুরোধে:

আপনি পরীক্ষার কেসটি এখানে সংক্ষিপ্ত করতে পারেন:

time bash -c 'f(){ :;};for i do f; done' {0..10000}

এটি $@বড় হওয়ার পরে এটি কোনও ফাংশনকে কল করছে যা মনে হয় এটি ট্রিগার করে।

আমার ধারণাটি হ'ল সময়টি $@একটি স্ট্যাকের উপর সঞ্চয় করা এবং পরে এটি পুনরুদ্ধার করতে ব্যয় করা হয়। সম্ভবত bashসমস্ত মান বা এর মতো কোনও কিছু সদৃশ করে এটি খুব অদক্ষতার সাথে করে। সময়টি o (n²) এ মনে হচ্ছে।

আপনি অন্যান্য শেলগুলিতে একই ধরণের সময় পান:

time zsh -c 'f(){ :;};for i do f "$@"; done' {0..10000}

যে যেখানে আপনি ফাংশন আর্গুমেন্টের তালিকায় পাস না, এবং এই সময় শেল দরকার (মান কপি করার bashআপ যে এক জন্য ধীর হিসাবে 5 বার হচ্ছে প্রান্ত)।

(আমি প্রথমে ভেবেছিলাম এটি বাশ ৫-এ আরও খারাপ ছিল (বর্তমানে আলফাতে রয়েছে), তবে এটি @ ইগমন্ট দ্বারা উল্লিখিত হিসাবে উন্নত সংস্করণগুলিতে ম্যালোক ডিবাগিং সক্ষম করা হয়েছিল; bashআপনি নিজের বিল্ডটি কীভাবে আপনার নিজের বিল্ডের সাথে তুলনা করতে চান তা পরীক্ষা করে দেখুন সিস্টেমের একটি instance উদাহরণস্বরূপ, উবুন্টু ব্যবহার করে --without-bash-malloc)


ডিবাগিং কীভাবে সরানো হয়?
আইজ্যাক

@isaac, আমি এটা পরিবর্তন করে করেনি RELSTATUS=alphaথেকে RELSTATUS=releaseconfigureস্ক্রিপ্ট।
স্টাফেন চেজেলাস

উভয় --without-bash-mallocএবং RELSTATUS=releaseপ্রশ্নের ফলাফলের জন্য পরীক্ষার ফলাফল যুক্ত করা হয়েছে । এটি এখনও এফ কল করার সাথে একটি সমস্যা দেখায়।
ইসহাক

@ ইসহাক, হ্যাঁ, আমি কেবল বলেছিলাম যে আমি বলছিলাম ভুল ছিল যে এটি বাশ 5 এর চেয়ে খারাপ ছিল। এটি খারাপ নয়, এটি ঠিক খারাপ।
স্টাফেন চেজেলাস

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