ইউনিভার্সাল নন-বাশ `সময়` বেঞ্চমার্ক বিকল্প? [বন্ধ]


10

বিভিন্ন শেলের মধ্যে স্ক্রিপ্টগুলির রান সময়কে তুলনা করার জন্য, কিছু এসই উত্তর bash' বিল্ট-ইন time কমান্ড ব্যবহার করার পরামর্শ দেয় , যেমন:

time bash -c 'foo.sh'
time dash -c 'foo.sh'

... ইত্যাদি , প্রতিটি শেল পরীক্ষা করার জন্য। এই জাতীয় মানদণ্ডগুলি প্রতিটি শেল লোড হওয়ার এবং নিজেকে আরম্ভ করার জন্য গৃহীত সময়কে হারাতে ব্যর্থ হয় । উদাহরণস্বরূপ, ধরুন উপরের দুটি কমান্ডই আস্তে আস্তে ফ্লপি ডিস্কের (124KB / s) পড়ার গতিতে ধীর ডিভাইসে সংরক্ষণ করা হয়েছিল , dash(একটি 150 ডলার এক্সিকিউটেবল) শেল ( ~ 1M ) এর চেয়ে প্রায় 7x দ্রুত লোড করবে লোডিংয়ের সময়গুলি সংখ্যাগুলিকে স্কিউ করে দেবে - শেলগুলি লোড হওয়ার পরে প্রতিটি শেলের নীচে রানের সময়গুলি পরিমাপ করার জন্য she শেলগুলির প্রাক-লোডিং সময় অপ্রাসঙ্গিক ।bashtimefoo.sh

স্ক্রিপ্ট টাইমিংয়ের জন্য চালানোর সেরা পোর্টেবল এবং সাধারণ ব্যবহার কী যা প্রতিটি শেলের মধ্যে থেকে চালানো যেতে পারে ? সুতরাং উপরের কোডটি এমন কিছু দেখবে:

bash -c 'general_timer_util foo.sh'
dash -c 'general_timer_util foo.sh'

এনবি: কোনও শেল বিল্ট-ইন time কমান্ড নেই, যেহেতু কোনওই বহনযোগ্য বা সাধারণ নয় are


ব্যবহারকারীর শেলটির অভ্যন্তরীণ কমান্ডগুলি এবং পাইপলাইনগুলির দ্বারা গ্রহণ করা সময়টিকে প্রথমে স্ক্রিপ্টে মোড়ানো না করেও যদি বেঞ্চমার্ক সক্ষম হয় তবে আরও ভাল। এই জাতীয় কৃত্রিম বাক্য গঠন সাহায্য করবে:

general_timer_util "while read x ; do echo x ; done < foo"

কিছু শেল timeএটি পরিচালনা করতে পারে। যেমন bash -c "time while false ; do : ; done"কাজ করে। আপনার সিস্টেমে কী কাজ করে (এবং না) তা দেখার জন্য চেষ্টা করুন:

tail +2 /etc/shells | 
while read s ; do 
    echo $s ; $s -c "time while false ; do : ; done" ; echo ----
done

6
শুধু ব্যবহার করবেন /usr/bin/time?
কুসালানন্দ

1
আমি বুঝতে পারি না যে কোনও অ-বিল্টিন সম্ভবত উভয়ই "প্রতিটি শেল লোড করতে এবং নিজেকে আরম্ভ করার জন্য নেওয়া সময়টি" কেটে ফেলতে পারে এবং "বহনযোগ্য এবং সাধারণ" হওয়ার সময় একটি স্বতন্ত্র স্ক্রিপ্ট কার্যকর করতে পারে।
মাইকেল হোমার

1
এটি প্রশ্নের উত্তর নয়, আপনি কী চান তা স্পষ্ট করার জন্য এটি একটি অনুরোধ।
মাইকেল হোমার

1
আমি আমার সেরা চেষ্টাটি পোস্ট করেছি, তবে আমি মনে করি যে প্রশ্নটি আসলে কী অর্জন করতে চাইছে ঠিক সে সম্পর্কে এখনও অবধারিত নয়।
মাইকেল হোমার

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

উত্তর:


10

আপনার লক্ষ করা উচিত যে timeএটি পসিক্স দ্বারা নির্দিষ্ট করা হয়েছে এবং আফিক একমাত্র বিকল্প যা পসিক্স উল্লেখ করেছে ( -p) বিভিন্ন শেল দ্বারা সঠিকভাবে সমর্থনযোগ্য:

$ bash -c 'time -p echo'

real 0.00
user 0.00
sys 0.00
$ dash -c 'time -p echo'

real 0.01
user 0.00
sys 0.00
$ busybox sh -c 'time -p echo'

real 0.00
user 0.00
sys 0.00
$ ksh -c 'time -p echo'       

real 0.00
user 0.00
sys 0.00

1
সমস্যাটি হ'ল সময়কে তুলনা করতে সক্ষম হতে একই ফলাফলটি একই বাস্তবায়নের মাধ্যমে সময় নির্ধারণ করতে হয় time। স্প্রিন্টারগুলি একই সময়ে এক ঘড়ির সাহায্যে না করে পৃথকভাবে 100 মিটারে তাদের নিজস্ব সময়কে পরিমাপ করার সাথে তুলনীয় ara এটি স্পষ্টতই
নিটপিক

@ কুসালানন্দ আমি ভেবেছিলাম যে সমস্যাটি হ'ল ওপি ভাবা যেত timeবহনযোগ্য নয়; এটি বহনযোগ্য বলে মনে হচ্ছে। (আমি, তুলনামূলক আপনার বিন্দু সাথে একমত যদিও)
muru

@ মুরু, আমার সিস্টেমে "সময়"dash -c 'time -p while false ; do : ; done' ফিরে আসে : সময় চলতে পারে না: এ জাতীয় কোনও ফাইল বা ডিরেক্টরি নেই <ক্রি> কমান্ডটি শূন্য-স্থিতি 127 " ত্রুটি সহ বেরিয়েছে
এজিসি

1
@agc POSIX আরও বলেছে: "শেল কম্পাউন্ড কমান্ড, পাইপলাইনস, বিশেষ বিল্ট-ইনস এবং আরও কিছু সরাসরি ব্যবহার করা যায় না এই বিষয়টি তুলে ধরে কমান্ডের পরিবর্তে ইউটিলিটি শব্দটি ব্যবহৃত হয়। তবে, ইউটিলিটিটিতে ব্যবহারকারী অ্যাপ্লিকেশন প্রোগ্রাম এবং শেল স্ক্রিপ্টগুলি, কেবল স্ট্যান্ডার্ড ইউটিলিটিগুলি নয়। " (বিভাগটি রেশনএল দেখুন)
মুরু


7

আমি জিএনইউ date কমান্ডটি ব্যবহার করি যা একটি উচ্চ রেজোলিউশন টাইমারকে সমর্থন করে:

START=$(date +%s.%N)
# do something #######################

"$@" &> /dev/null

#######################################
END=$(date +%s.%N)
DIFF=$( echo "scale=3; (${END} - ${START})*1000/1" | bc )
echo "${DIFF}"

এবং তারপরে আমি স্ক্রিপ্টটিকে এভাবে কল করি:

/usr/local/bin/timing dig +short unix.stackexchange.com
141.835

আউটপুট ইউনিটটি মিলি সেকেন্ডে রয়েছে।


1
সময় (যুগের সময়) ধরে নেওয়া মধ্যবর্তী সময়ে পরিবর্তন হয় না। বাস্তবে এমন কোনও ক্ষেত্রে ভাবতে পারি না যেখানে এটি সমস্যার কারণ হয়ে দাঁড়ায় তবে এখনও উল্লেখ করার মতো।
phk

1
আপনার যুক্ত করা উচিত যে এটির জন্য dateবিশেষত জিএনইউ প্রয়োজন ।
কুসালানন্দ

@ পিএফকে দয়া করে ব্যাখ্যা করুন?
রবিন

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

1
এছাড়াও, কিছু এনটিপি ক্লায়েন্ট সিস্টেম সময়টিতে "লাফিয়ে" তৈরি করার পরিবর্তে ধীরে ধীরে এবং ঘড়ির গতি বাড়ায় না? যদি আপনার মতো এনটিপি ক্লায়েন্ট থাকে এবং আপনি গতকাল সন্ধ্যায় কিছু সময় তৈরি করেছেন, তবে সম্ভবত এনটিপি ক্লায়েন্ট লিপ সেকেন্ডটিকে "প্রত্যাশিত" করতে পারে। (বা কেবল সেই ক্ষেত্রে সিস্টেমের ঘড়িটি 61 এ চলে?)
জার্গ ডব্লু মিত্তাগ

6

timeউপযোগ সাধারণত শেল মধ্যে তৈরি, হিসাবে আপনি লক্ষ্য করে থাকবেন, যা এটি একটি "নিরপেক্ষ" টাইমার হিসাবে বেহুদা করে তোলে।

তবে, ইউটিলিটিটি সাধারণত বাহ্যিক ইউটিলিটি হিসাবে উপলভ্য হয় /usr/bin/time, এটি আপনার প্রস্তাবিত সময় পরীক্ষাগুলি সম্পাদন করতে ভালভাবে ব্যবহৃত হতে পারে।

$ bash -c '/usr/bin/time foo.sh'

এটি কীভাবে "প্রতিটি শেল লোড করার এবং নিজেকে আরম্ভ করার জন্য নেওয়া সময়কে সরিয়ে দেয়"?
মাইকেল হোমার

1
যদি foo.shএক্সিকিউটেবল হয় এবং একটি শেবাং থাকে, তবে এটি সর্বদা এটি একই শেল দিয়ে চালায় এবং এটি সেই শেলের প্রারম্ভকালীন সময় গণনা করে, সুতরাং ওপি এটি চায় না। যদি foo.shসেগুলির মধ্যে একটি অনুপস্থিত থাকে তবে এটি মোটেই কার্যকর হয় না।
কেভিন

@ কেভিন খুব সত্য আমি মনে করি কেবল "অন্তর্নির্মিত কোনও শেল নেই time" মনে হয়েছে। শেল শুরুর সময়টি আলাদাভাবে মাপতে হতে পারে।
কুসালানন্দ

1
timeবিল্টিন কমান্ড থাকা কোনও শেল সম্পর্কে আমি জানি না । তবে অনেকগুলি শেলের bashএকটি timeকীওয়ার্ড রয়েছে যা সময় পাইপলাইনে ব্যবহৃত হতে পারে। এই কীওয়ার্ডটি অক্ষম করতে যাতে timeকমান্ডটি (ফাইল সিস্টেমে) ব্যবহৃত হয়, আপনি এটির মতো উদ্ধৃতি দিতে পারেন "time" foo.sh। এছাড়াও unix.stackexchange.com/search?q=user%3A22565+
স্টাফেন

6

এখানে একটি সমাধান যা:

  1. প্রতিটি শেল নিজেকে লোড করতে এবং আরম্ভ করার জন্য নেওয়া সময়কে [গুলি] বাদ দিন

  2. প্রতিটি শেলের মধ্যে থেকে চালানো যেতে পারে

  3. ব্যবহারসমূহ

    কোনও শেল অন্তর্নির্মিত timeকমান্ড নেই, যেহেতু কোনওই বহনযোগ্য বা সাধারণ নয়

  4. সমস্ত পসিক্স-সামঞ্জস্যপূর্ণ শেলগুলিতে কাজ করে।
  5. একটি সি সংকলক সহ সমস্ত পসিক্স-সামঞ্জস্যপূর্ণ এবং এক্সএসআই-কনফর্মিং সিস্টেমগুলিতে কাজ করে বা যেখানে আপনি আগে থেকে সি নির্বাহযোগ্য কে সংকলন করতে পারেন।
  6. সমস্ত শেলগুলিতে একই সময় বাস্তবায়ন ব্যবহার করে।

দুটি অংশ রয়েছে: একটি সংক্ষিপ্ত সি প্রোগ্রাম যা গুটিয়ে রাখে gettimeofday, যা অবনমিত তবে এখনও তার চেয়ে বেশি পোর্টেবল clock_gettimeএবং একটি শর্ট শেল স্ক্রিপ্ট যা সেই প্রোগ্রামটিকে একটি স্ক্রিপ্টের সোসাইংয়ের উভয় পক্ষের একটি মাইক্রোসেকেন্ড-নির্ভুলতা ঘড়ি পেতে পড়তে ব্যবহার করে। সি প্রোগ্রাম হ'ল একমাত্র পোর্টেবল এবং ন্যূনতম-ওভারহেড উপায় যা কোনও টাইমস্ট্যাম্পে উপ-দ্বিতীয় নির্ভুলতা পেতে পারে।

সি প্রোগ্রামটি এখানে epoch.c:

#include <sys/time.h>
#include <stdio.h>
int main(int argc, char **argv) {
    struct timeval time;
    gettimeofday(&time, NULL);
    printf("%li.%06i", time.tv_sec, time.tv_usec);
}

এবং শেল স্ক্রিপ্ট timer:

#!/bin/echo Run this in the shell you want to test

START=$(./epoch)
. "$1"
END=$(./epoch)
echo "$END - $START" | bc

এটি স্ট্যান্ডার্ড শেল কমান্ড ভাষা এবং bcকোনও পসিক্স-সামঞ্জস্যপূর্ণ শেলের অধীনে স্ক্রিপ্ট হিসাবে কাজ করা উচিত।

আপনি এটি হিসাবে ব্যবহার করতে পারেন:

$ bash timer ./test.sh
.002052
$ dash timer ./test.sh
.000895
$ zsh timer ./test.sh
.000662

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

পরিবর্তিত টাইমার স্ক্রিপ্ট স্ক্রিপ্টের evalবাইরে কমান্ড চালানোর জন্য ব্যবহার করতে পারে ।


কাকতালীয়ভাবে, এটি পড়ার ঠিক আগে, (এবং শেষ পংক্তিতে eval), আমি রবিনের উত্তরটি অন্তর্ভুক্ত করার জন্য স্ক্রিপ্টটি টুইট করছিeval "$@" , যাতে এটি উড়ে শেল বিল্টিনগুলি চালাতে পারে।
এজিসি

4

একাধিকবার সংশোধিত সমাধান /proc/uptimeএবং dc/ bc/ awkবৃহত অংশগুলিতে এ.সি.সি. দ্বারা ইনপুটকে ধন্যবাদ ব্যবহার করে :

#!/bin/sh

read -r before _ < /proc/uptime

sleep 2s # do something...

read -r after _ < /proc/uptime

duration=$(dc -e "${after} ${before} - n")
# Alternative using bc:
#   duration=$(echo "${after} - ${before}" | bc)
# Alternative using awk:
#   duration=$(echo "${after} ${before}" | awk '{print $1 - $2}')

echo "It took $duration seconds."

অনুমান যে স্পষ্টভাবে /proc/uptimeবিদ্যমান এবং একটি নির্দিষ্ট ফর্ম আছে।


3
এটি শেলগুলির মধ্যে এটি বহনযোগ্য করে তুলবে, তবে ইউনিক্স বাস্তবায়নের মধ্যে বহনযোগ্য নয় কারন কারও কারও কাছে কেবল /procফাইল সিস্টেমের অভাব রয়েছে । এটি যদি উদ্বেগজনক বা না থাকে তবে আমি জানি না।
কুসালানন্দ

1
জোর দেওয়ার জন্য এই কিউ ফ্লপি ডিস্কের গতি বা আরও খারাপ প্রস্তাব দেয়। যে ক্ষেত্রে লোডিং এর ওভারহেড awkতাৎপর্যপূর্ণ হতে পারে। সম্ভবত b=$(cat /proc/uptime)আগে, তারপরে a=$(cat /proc/uptime), পরে পার্স $ এ এবং $ বি এবং বিয়োগ করে।
এগ্রি

@agc ভাল ইনপুট, ধন্যবাদ, আমি সে অনুযায়ী কিছু বিকল্প সমাধান যুক্ত করেছি।
phk

1
আগে এটি মনে করেন না, কিন্তু যদি builtins পছন্দ readচেয়ে ভাল cat: সঙ্গে, এই ক্লিনার হবে (এবং একটি সামান্য দ্রুত) read before dummyvar < /proc/uptime ;sleep 2s;read after dummyvar < /proc/uptime; duration=$(dc -e "${after} ${before} - n");echo "It took $duration seconds."
AGC
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.