यूनिवर्सल नॉन-बैश `टाइम` बेंचमार्क विकल्प? [बन्द है]


10

विभिन्न गोले के बीच लिपियों के चलाने के समय की तुलना के लिए, कुछ एसई जवाब उपयोग करने का सुझाव bash'एस में निर्मित time आदेश है, इसलिए की तरह:

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

... आदि , हर खोल के लिए परीक्षण करने के लिए। इस तरह के मानदंड प्रत्येक शेल के लिए खुद को लोड करने और आरंभ करने के लिए लिए गए समय को समाप्त करने में विफल होते हैं । उदाहरण के लिए, मान लें कि उपरोक्त दोनों कमांड एक धीमी गति से डिवाइस पर जल्दी फ्लॉपी डिस्क , (124KB / s), dash( ~ 150K निष्पादन योग्य) की रीड गति के साथ संग्रहीत की गई ( ~ 1M ) शेल से लगभग 7x तेज़ी से लोड होगी लोडिंग समय संख्याओं को तिरछा करेगा - गोले लोड होने के बाद प्रत्येक शेल के रन समय को मापने के लिए उन गोले के पूर्व-लोडिंग समय अप्रासंगिक हो सकते हैं ।bashtimefoo.sh

स्क्रिप्ट के समय को चलाने के लिए सबसे अच्छा पोर्टेबल और सामान्य उपयोग क्या है जो प्रत्येक शेल के भीतर से चलाया जा सकता है ? तो उपरोक्त कोड कुछ इस तरह दिखाई देगा:

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

एनबी: कोई शेल -इन- time कमांड नहीं है, क्योंकि कोई भी पोर्टेबल या सामान्य नहीं है।


यदि उपयोगकर्ता किसी स्क्रिप्ट में पहली बार लपेटने के बिना शेल के आंतरिक आदेशों और पाइपलाइनों द्वारा लिए गए समय को बेंचमार्क करने में सक्षम है, तो भी बेहतर है। इस तरह कृत्रिम वाक्य रचना में मदद मिलेगी:

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?
Kusalananda

1
मुझे समझ में नहीं आता है कि कोई भी गैर-बिल्डिन संभवतः दोनों को "पोर्टेबल और सामान्य होने के दौरान" प्रत्येक शेल को लोड करने और शुरू करने के लिए उठाए गए समय को समाप्त कर सकता है और एक स्टैंडअलोन स्क्रिप्ट निष्पादित कर सकता है।
माइकल होमर

1
यह सवाल का जवाब नहीं है, आपके लिए यह स्पष्ट करना है कि आप क्या चाहते हैं।
माइकल होमर

1
मैंने अपना सर्वश्रेष्ठ प्रयास पोस्ट किया है, लेकिन मुझे लगता है कि यह सवाल अभी भी रेखांकित नहीं है कि वास्तव में यह क्या हासिल करने की कोशिश कर रहा है।
माइकल होमर

2
"पोर्टेबल या सामान्य" से आपका क्या तात्पर्य है? शेल बिल्डरों के रूप में पोर्टेबल होते हैं (कई प्रणालियों पर काम करते हैं) और अधिक सामान्य (अधिक परिस्थितियों में काम करते हैं, क्योंकि वे बाहरी कमांड के रूप में फ़ाइल के निष्पादन के अलावा कुछ और कर सकते हैं)। आप कौनसी समस्याएं हल करने की कोशिश कर रहे हैं?
गाइल्स का SO- बुराई से दूर

जवाबों:


10

आपको ध्यान देना चाहिए कि timePOSIX द्वारा निर्दिष्ट किया गया है , और AFAICT एकमात्र विकल्प है जो POSIX उल्लेख ( -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 मीटर पर अपना समय मापने की तुलना करने के लिए तुलनीय है। यह स्पष्ट रूप से nitpicking है, लेकिन अभी भी ...
Kusalananda

@ कुसलानंद ने सोचा कि समस्या यह थी कि ओपी ने सोचा timeकि यह पोर्टेबल नहीं है; यह पोर्टेबल लगता है। (मैं तुलनीयता पर आपकी बात से सहमत हूं, हालांकि)
मुरु

@muru, अपने सिस्टम पर dash -c 'time -p while false ; do : ; done'रिटर्न "समय: नहीं चल सकता है, जबकि: ऐसी कोई फ़ाइल या निर्देशिका <करोड़> कमान गैर शून्य स्थिति 127 के साथ बाहर निकल गया" त्रुटियों।
बजे

1
@agc POSIX यह भी कहता है: "इस शब्द की उपयोगिता का उपयोग कमांड के बजाए, इस तथ्य को उजागर करने के लिए किया जाता है कि शेल कंपाउंड कमांड, पाइपलाइन, विशेष बिल्ट-इन, और इतने पर सीधे उपयोग नहीं किया जा सकता है। हालांकि, उपयोगिता में उपयोगकर्ता एप्लिकेशन प्रोग्राम शामिल हैं। शेल स्क्रिप्ट्स, न केवल मानक उपयोगिताओं। " (खंड राष्ट्रीय देखें)
muru

1
muru

7

मैं GNU 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विशेष रूप से जीएनयू की आवश्यकता है ।
Kusalananda

@ कृपया समझाएं?
राबिन

1
@ राबिन अपने एनटीपी क्लाइंट मुद्दों को कहते हैं और अपडेट करते हैं STARTऔर जहां और ENDसेट के बीच अपनी घड़ी को बदलते हैं , तो यह स्पष्ट रूप से आपके परिणाम को प्रभावित करेगा। पता नहीं आपको इसकी कितनी सही जरूरत है और क्या यह आपके मामले में मायने रखता है, लेकिन जैसा कि मैंने कहा, कुछ को ध्यान में रखना चाहिए। (मजेदार कहानी: मैं एक सॉफ्टवेयर को जानता हूं, जहां वास्तव में यह अप्रत्याशित रूप से नकारात्मक परिणामों का कारण बना - इसका उपयोग थ्रूपुट गणनाओं के लिए किया गया था - जो तब कुछ चीजों को तोड़ देता था।)
phk

1
इसके अलावा, सिस्टम के समय में "कूद" बनाने के बजाय कुछ एनटीपी क्लाइंट घड़ी को धीमा और गति नहीं देते हैं? यदि आपके पास उस तरह का एक एनटीपी क्लाइंट है, और आपने कल शाम को कुछ समय बनाया है, तो वे शायद एनपीपी क्लाइंट द्वारा लीप सेकेंड का "अनुमान" कर रहे हैं। (या सिस्टम क्लॉक सिर्फ उस मामले में 61 तक चलता है?)
जॉर्ग डब्ल्यू मित्तग

6

timeउपयोगिता आम तौर पर खोल में बनाया गया है, जैसा कि आप देखा है, जो इसे एक "निष्पक्ष" टाइमर के रूप में बेकार बना देता है।

हालाँकि, उपयोगिता आमतौर पर एक बाहरी उपयोगिता के रूप में भी उपलब्ध है /usr/bin/time, जिसका उपयोग आपके द्वारा प्रस्तावित समय प्रयोगों को करने के लिए अच्छी तरह से किया जा सकता है।

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

यह "प्रत्येक शेल के लिए खुद को लोड और इनिशियलाइज़ करने में लगने वाले समय को कैसे समाप्त करता है"?
माइकल होमर

1
यदि foo.shनिष्पादन योग्य है और उसके पास एक शेलबैंग है, तो यह हमेशा इसे एक ही शेल से चलाता है, और यह उस शेल के स्टार्टअप समय की गणना करता है, इसलिए यह वह नहीं है जो ओपी चाहता है। यदि foo.shउनमें से एक भी गायब है, तो यह बिल्कुल भी काम नहीं करता है।
केविन

@ केविन बहुत सच है। मैंने केवल "नो शेल बिल्ट-इन time" को ध्यान में रखा, ऐसा लगता है। शेल स्टार्टअप समय को अलग से मापा जा सकता है।
Kusalananda

1
मुझे किसी भी शेल के बारे में पता नहीं है जिसमें एक timeबिलिन कमांड है। हालाँकि कई शेल bashमें एक timeकीवर्ड होता है जिसका उपयोग समय पाइपलाइनों के लिए किया जा सकता है। उस कीवर्ड को निष्क्रिय करने के लिए timeकमांड (फाइल सिस्टम में) का उपयोग किया जाता है, आप इसे पसंद कर सकते हैं "time" foo.sh। यह भी देखें unix.stackexchange.com/search?q=user%3A22565+time+keyword
स्टीफन Chazelas

6

यहाँ एक समाधान है कि:

  1. प्रत्येक शेल को स्वयं लोड करने और आरंभ करने के लिए लिया गया समय समाप्त करें

  2. प्रत्येक खोल के भीतर से चलाया जा सकता है

  3. उपयोग

    कोई शेल अंतर्निहित timeकमांड नहीं है, क्योंकि कोई भी पोर्टेबल या सामान्य नहीं है

  4. सभी POSIX- संगत गोले में काम करता है।
  5. सभी POSIX- संगत और XSI- अनुरूपण सिस्टम पर एक सी संकलक के साथ काम करता है , या जहां आप पहले से निष्पादन योग्य C संकलित कर सकते हैं।
  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किसी भी POSIX- संगत शेल के तहत एक स्क्रिप्ट के रूप में काम करना चाहिए।

आप इसका उपयोग इस प्रकार कर सकते हैं:

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

यह सिस्टम या उपयोगकर्ता के समय को मापता नहीं है, केवल गैर-मोनोटोनिक दीवार-घड़ी बीता हुआ समय है। यदि स्क्रिप्ट के निष्पादन के दौरान सिस्टम क्लॉक बदलता है, तो यह गलत परिणाम देगा। यदि सिस्टम लोड में है, तो परिणाम अविश्वसनीय होगा। मुझे नहीं लगता कि शेल के बीच कुछ भी बेहतर पोर्टेबल हो सकता है।

एक संशोधित टाइमर स्क्रिप्ट स्क्रिप्ट के evalबाहर कमांड चलाने के बजाय उपयोग कर सकती है ।


संयोग से, इसे पढ़ने से पहले, (और अंतिम पंक्ति के बारे में eval), मैं स्क्रिप्ट को रबिन के उत्तर में शामिल करने के लिए लिख रहा था eval "$@", इसलिए यह मक्खी पर शेल बिल्डरों को चला सकता था ।
23

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फाइल सिस्टम की कमी है । अगर यह चिंता का विषय है या नहीं, मुझे नहीं पता।
Kusalananda

1
जोर देने के लिए यह Q फ्लॉपी डिस्क गति या बदतर का सुझाव देता है। जिस स्थिति में लोडिंग का ओवरहेड awkमहत्वपूर्ण हो सकता है। शायद b=$(cat /proc/uptime)पहले, उसके a=$(cat /proc/uptime)बाद, फिर $ a और $ b पार्स करें और घटाएं।
अगस्त

@agc अच्छा इनपुट, धन्यवाद, मैंने तदनुसार कुछ वैकल्पिक समाधान जोड़े।
phk

1
इसके बारे में पहले नहीं सोचा था, लेकिन अगर बिल्टिन की तरह 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.