לוגו אתר Fresh          
 
 
  אפשרות תפריט  ראשי     אפשרות תפריט  צ'אט     אפשרות תפריט  מבזקים     אפשרות תפריט  צור קשר     חץ שמאלה ‎print ‎"Hello World!"; if‎ ‎not rules.‎know ‎then rules.‎read(); חץ ימינה  

לך אחורה   לובי הפורומים > מחשבים > תכנות ובניית אתרים
שמור לעצמך קישור לדף זה באתרי שמירת קישורים חברתיים
תגובה
 
כלי אשכול חפש באשכול זה



  #1  
ישן 14-08-2007, 23:11
  DCD DCD אינו מחובר  
 
חבר מתאריך: 17.05.05
הודעות: 7,321
תחליף ללולאת ה-foreach ; מהיר יותר, ייתכן?

נתקפתי בחשק עז לבדוק מהירויות, וכתבתי את הקוד הבא:

קוד PHP:
 function microtime_float()
{
    list(
$usec$sec) = explode(" "microtime());
    return ((float)
$usec + (float)$sec);
}
$timeCollector 0.0;

$words = array(    'hello' => 'world!',
                
'I' => 'am',
                
'trying' => 'to',
                
'check' => 'which',
                
'way' => 'would',
                
'be' => 'faster',
                
'than' => 'the',
                
'other' => 'one',
                
'It' => 'takes',
                
'time' => 'to',
                
'fill' => 'this',
                
'long' => 'annoying',
                
'array' => 'Too',
                
'much' => 'time',
                
'It_2' => 'is',
                
'specially' => 'for',
                
'checking' => 'it',
                
'performance' => '...',
                
'word' => 'WORDS'
                
);
$loopIt 1000;
for(
$i=0$i<$loopIt; ++$i)
{
    
$timeBefore microtime_float();
    
/* THE ACTION */
    
    /*    //FOREACH LOOP
    foreach($words as $v)
        echo $v.'<br />';
    */
        //FOR LOOP
    
$_words = array(    'hello',
                    
'I',
                    
'trying',
                    
'check',
                    
'way',
                    
'be',
                    
'than',
                    
'other',
                    
'It',
                    
'time',
                    
'time',
                    
'fill',
                    
'long',
                    
'array',
                    
'much',
                    
'It_2',
                    
'specially',
                    
'checking',
                    
'performance',
                    
'word'
                
);
    for(
$x=0; isset($_words[$x]); ++$x)
        echo 
$words[$_words[$x]].'<br />';
    
    
$timeCollector += (microtime_float()) - $timeBefore;
}

echo 
'<br /><br />Operation took: '.($timeCollector/$loopIt); 


אם תשימו לב, כשתריצו אותו תבחינו שלולאת ה-FOR מהירה בהרבה מלולאת ה-FOREACH (או שתשימו לב שאני גרוע בחישוב מתמטי ובהבנת המושג E.)

בכל מקרה, כשהרצתי את לולאת ה-for יצא לי שהזמן הוא:
קוד:
4.88111972809E-005

וכשהרצתי את לולאת ה-foreach יצא לי:
קוד:
2.82213687897E-005


בהנחה ש-E זה חזקה, יוצא שלולאת ה-FOR הרבה יותר מהירה, בצורה משמעותית, מלולאת ה-FOREACH.
הגיוני? זה נכון?
תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
  #7  
ישן 23-08-2007, 02:04
  ישראל K ישראל K אינו מחובר  
 
חבר מתאריך: 25.08.03
הודעות: 9,114
בתגובה להודעה מספר 1 שנכתבה על ידי DCD שמתחילה ב "תחליף ללולאת ה-foreach ; מהיר יותר, ייתכן?"

אולי לא שמת לב, אבל יש פה כמה וכמה טעויות בסיסיות.
אשתדל לציין את כל מה שנתקלתי, לא בהכרח לפי הסדר...

1. בלולאת ה-for שיישמת במקום לולאת ה-foreach אתה עושה שימוש בפונקציה/פקודה isset, דבר שמוטעה. למיטב זכרוני מצויין במפורש בתיעוד הרשמי שלבדיקה כזאת לאיבר במערך צריך להשתמש בפונקציה array_key_exists (כיון ששימוש ב-isset יחזיר שקר אם האיבר יכיל את הערך NULL גם אם הוא כן קיים). [אני כותב מהזיכרון, כנ"ל לגבי שאר הדברים, לו יתברר שזכרתי לא נכון, אשמח אם תצרף את הציטוט ואחזור בי, אבל בפירוש כך זכור לי].
2. הבחירה בין מערך אסוציאטיבי למערך מספרי, אינה בהכרח לפי מהירות וביצועים, אלא בהתאם לצורך.
3. ההשוואה הזאת ממש לא נכונה, כיון שאתה משווה סוג נתונים שונה. השוואת זמן ריצה אמיתית צריכה להעשות על אותו מערך עם צורת גישה שונה למערך, כך שבמקרה זה תצטרך לבדוק את foreach על מערך מספרי ולא על מערך אסוציאטיבי.

הרצתי בדיקה בהתאם להערות שכתבתי לעיל וכפי שתוכלו לראות להלן (התוצאות יוצגו לאחר פיסקה זו והקוד בסוף ההודעה) במבט ראשון נראה שלולאת foreach אוכלת בלי מלח את לולאת for, היא מהירה במעט יותר מכפול ממהירות לולאת ה-for.
אבל, כפי שהזכרתי לפני כן, כדי לבצע בדיקה "אמיתית", חייבים לבצע את הבדיקה בדיוק באותו אופן וזה לא נעשה ממש כך, כיון שבלולאת ה-for ישנה פעולה אחת יותר מאשר ב-foreach, הפעולה הנוספת היא קריאה לפונקציה count, דבר שמהבדיקה כפי שתראו להלן, מראה שהיא מאד משמעותית, שכן, בלעדיה זמן הריצה הוא לעתים אף פחות מחצי הזמן. לכן צירפתי את הבדיקה הרביעית והאחרונה בה אני שומר את הערך של הפונקציה count במשתנה, כדי למנוע בזבוז זמן בקריאה חוזרת לפונקציה כשאותו ערך כלל לא השתנה. פעולה זו מגלה שטעינו והבדל משך זמן הריצה בין לולאת foreach ולולאת for אינו קבוע ואינו משמעותי כלל וכלל, גם לא כשמדובר במערך ענק ומספר ריצות רב. לעתים הראשון יראה תוצאות מעט מאד מהירות יותר, ובמקרים אחרים, האחרון יראה תוצאות מעט מאד מהירות יותר מהראשון.
יש להשים לב שמדובר כאן בריצה של 10,000 פעמים והפרש הזמן הוא לעתים פחות מעשירית השניה, מה שאומר שבזמן ריצה רגיל הפער יהיה אפילו לא רבע אלפית השניה... בנוסף לכך שמדובר במערך בגודל בינוני (20 איברים הוא להערכתי מערך בגדול בינוני, אם כי מערך גדול הייתי קורא לכזה שהוא גדול ממנו ביותר מפי שניים ושלושה, כיון שרוב המערכים קטנים יותר).

בשורה התחתונה: אף לולאה לא מהירה יותר, כך שהבחירה בין הלולאות תעשה לפי נוחות ולא לפי מהירות.

הערה: ההשוואה האמיתית נעשית בין הבדיקה השניה והרביעית בתוצאות והקוד שלהלן:
קוד:
Loop: foreach. Array: associative. 10000 times. 0.091490983963013 Sec Loop: foreach. Array: numeric. 10000 times. 0.090087890625 Sec Loop: for. Array: numeric (with count() function). 10000 times. 0.17708587646484 Sec Loop: for. Array: numeric (without count() function). 10000 times. 0.09605598449707 Sec Total: 0.45491504669189 Sec


קוד PHP:
<?php

$total_time_start 
array_sum(explode(' ',microtime()));


$assoc = array(
    
'hello' => 'world!',
    
'I' => 'am',
    
'trying' => 'to',
    
'check' => 'which',
    
'way' => 'would',
    
'be' => 'faster',
    
'than' => 'the',
    
'other' => 'one',
    
'It' => 'takes',
    
'time' => 'to',
    
'fill' => 'this',
    
'long' => 'annoying',
    
'array' => 'Too',
    
'much' => 'time',
    
'It_2' => 'is',
    
'specially' => 'for',
    
'checking' => 'it',
    
'performance' => '...',
    
'word' => 'WORDS'
    
);

$numeric = array(
    
'hello',
    
'I',
    
'trying',
    
'check',
    
'way',
    
'be',
    
'than',
    
'other',
    
'It',
    
'time',
    
'time',
    
'fill',
    
'long',
    
'array',
    
'much',
    
'It_2',
    
'specially',
    
'checking',
    
'performance',
    
'word');


$times 10000;

header('Content-Type: text/plain');

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i)
    foreach(
$assoc as $v){}
echo 
"\n\nLoop: foreach.\nArray: associative.\n$times times. ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';


$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i)
    foreach(
$numeric as $v){}
echo 
"\n\nLoop: foreach.\nArray: numeric.\n$times times. ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';


$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i)
    for(
$j=0$j<count($numeric); ++$j){}
echo 
"\n\nLoop: for.\nArray: numeric (with count() function).\n$times times. ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';


$time_start array_sum(explode(' ',microtime()));
$count count($numeric);
for(
$i=0$i<$times; ++$i)
    for(
$j=0$j<$count; ++$j){}
echo 
"\n\nLoop: for.\nArray: numeric (without count() function).\n$times times. ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';


echo 
"\n\n\nTotal: ".(array_sum(explode(' ',microtime())) - $total_time_start).' Sec';

?>

נערך לאחרונה ע"י ישראל K בתאריך 23-08-2007 בשעה 02:18.
תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
  #8  
ישן 23-08-2007, 19:01
  DCD DCD אינו מחובר  
 
חבר מתאריך: 17.05.05
הודעות: 7,321
בתגובה להודעה מספר 7 שנכתבה על ידי ישראל K שמתחילה ב "אולי לא שמת לב, אבל יש פה כמה..."

ציטוט:
בלולאת ה-for שיישמת במקום לולאת ה-foreach אתה עושה שימוש בפונקציה/פקודה isset, דבר שמוטעה. למיטב זכרוני מצויין במפורש בתיעוד הרשמי שלבדיקה כזאת לאיבר במערך צריך להשתמש בפונקציה array_key_exists (כיון ששימוש ב-isset יחזיר שקר אם האיבר יכיל את הערך NULL גם אם הוא כן קיים). [אני כותב מהזיכרון, כנ"ל לגבי שאר הדברים, לו יתברר שזכרתי לא נכון, אשמח אם תצרף את הציטוט ואחזור בי, אבל בפירוש כך זכור לי].


צודק, לפרטים: isset.
אני עושה את הבדיקה בהנחה שלא ייקבע ערך NULL בערכי המערך.

ציטוט:
2. הבחירה בין מערך אסוציאטיבי למערך מספרי, אינה בהכרח לפי מהירות וביצועים, אלא בהתאם לצורך.
3. ההשוואה הזאת ממש לא נכונה, כיון שאתה משווה סוג נתונים שונה. השוואת זמן ריצה אמיתית צריכה להעשות על אותו מערך עם צורת גישה שונה למערך, כך שבמקרה זה תצטרך לבדוק את foreach על מערך מספרי ולא על מערך אסוציאטיבי.


עשיתי את הבדיקה הזאת כדי לראות באמצעות איזו שיטה אצליח לעבור על כל איברי המערך בצורה המהירה ביותר.
אין פה השוואה בין לולאות...אלא בין שיטות.

המטרה הסופית היא לגשת אל הערכים של המערך בזמן הקצר ביותר.
ד"א בגלל זה עשיתי את ההרצה עם הפונקציה isset, אני מניח שהיא מהירה יותר מהרבה פונקציות אחרות וגם מהירה יותר מהפונקציה array_key_exists.

---------------

4. (חוץ מהנ"ל,) בבדיקה שעשית שמתי לב שאת הטעינה של המערך numeric$ עשית מחוץ לריצת הלולאות.
אני בכוונה שמתי את הטעינה של המערך בתוך הלולאות כי זה נחשב חלק מה"שיטה" שמבוצעת בעזרת הלולאה FOR, ולכן צריך לקחת בחשבון את זמן הטעינה של המערך (איני יודע כמה זמן לוקח לטעון מערך, ולא התאמצתי לבדוק, לכן העדפתי לכלול אותו בתוך הלולאה גם אם הזמן אינו משמעותי).


אחלה השקעה, תודה על התגובה והמידע
תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
  #9  
ישן 26-08-2007, 02:22
  ישראל K ישראל K אינו מחובר  
 
חבר מתאריך: 25.08.03
הודעות: 9,114
בתגובה להודעה מספר 8 שנכתבה על ידי DCD שמתחילה ב "[QUOTE]בלולאת ה-for שיישמת..."

isset באמת מהיר יותר מהפונקציה המקבילה לבדיקת איבר במערך, במיוחד מערך אסוציאטיבי (במערך רגיל הפער ממש ממש קלוש).
בכל אופן, זה לא ממש רלוונטי כשזה בעצם לא עושה את הפעולה הדרושה, כי אם איבר אחד יכיל את הערך null, ריצת הלולאה תופסק גם אם נותרו עשרות, מאות, אלפי או יותר איברים המכילים ערכים יותר רלוונטיים. (וגם null הוא ערך שיכול להיות מאד רלוונטי במקרים מסויימים).
מה שכן, יתכן ושימוש בשני הפונקציות יחד באמצעות OR כש-isset הוא הראשון, יהיה יעיל יותר.
אני מצרף קטע קוד לדוגמא:
קוד PHP:
<?
if(isset($arr['a']) || array_key_exists('a', $array))
{
    // Some code
}

//...

while(isset($arr['a']) || array_key_exists('a', $array))
{
    // Some code
}
?>


בנוסף, אני מצרף את קוד ה-php שהרצתי לצורך השוואת זמן הריצה בין isset ל-array_key_exists.
מדובר בקוד מעט ארוך, כיון שעשיתי בדיקות על מערכים בעלי סוג שונה, אורך שונה, בדיקת איבר בתחילת המערך, באמצע המערך, חורג בהרבה מתחום המערך וכדומה. (אני מניח שמבחינת הביצוע אין הבדל בין בדיקת איבר שתיאורטית חורג בהרבה מהיסט סוף המערך לבין איבר שתיאורטית נמצא בבית הבא שלאחר סיום המערך).
קוד PHP:
<?php

$total_time_start 
array_sum(explode(' ',microtime()));

$times 100000// 1,000,000;

header('Content-Type: text/plain');

echo 
"\n\n--- Times: ".number_format($times)." ---\n\n\n";


$array = array(true);

echo 
"Array type: numeric\nCount: ".count($array)."\nKey: 0";

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    isset(
$array[0]);
echo 
"\n\nFunction: isset\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    
array_key_exists(0$array);
echo 
"\n\nFunction: array_key_exists\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';



$array = array(true);

echo 
"\n\n------------------------\n\n";
echo 
"Array type: numeric\nCount: ".count($array)."\nKey: 1";

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    isset(
$array[1]);
echo 
"\n\nFunction: isset\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    
array_key_exists(1$array);
echo 
"\n\nFunction: array_key_exists\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';



$array = array(true);

echo 
"\n\n------------------------\n\n";
echo 
"Array type: numeric\nCount: ".count($array)."\nKey: 1000";

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    isset(
$array[1000]);
echo 
"\n\nFunction: isset\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    
array_key_exists(1000$array);
echo 
"\n\nFunction: array_key_exists\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';



$array = array(1234567891011121314151617181920);

echo 
"\n\n------------------------\n\n";
echo 
"Array type: numeric\nCount: ".count($array)."\nKey: 0";

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    isset(
$array[0]);
echo 
"\n\nFunction: isset\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    
array_key_exists(0$array);
echo 
"\n\nFunction: array_key_exists\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';



$array = array(1234567891011121314151617181920);

echo 
"\n\n------------------------\n\n";
echo 
"Array type: numeric\nCount: ".count($array)."\nKey: 0";

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    isset(
$array[15]);
echo 
"\n\nFunction: isset\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    
array_key_exists(15$array);
echo 
"\n\nFunction: array_key_exists\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';



$array = array(1234567891011121314151617181920);

echo 
"\n\n------------------------\n\n";
echo 
"Array type: numeric\nCount: ".count($array)."\nKey: 1000";

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    isset(
$array[1000]);
echo 
"\n\nFunction: isset\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    
array_key_exists(1000$array);
echo 
"\n\nFunction: array_key_exists\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';



$array = array('a'=>1);

echo 
"\n\n------------------------\n\n";
echo 
"Array type: associative\nCount: ".count($array)."\nKey: a";

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    isset(
$array['a']);
echo 
"\n\nFunction: isset\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    
array_key_exists('a'$array);
echo 
"\n\nFunction: array_key_exists\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';



$array = array('a'=>1);

echo 
"\n\n------------------------\n\n";
echo 
"Array type: associative\nCount: ".count($array)."\nKey: h";

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    isset(
$array['h']);
echo 
"\n\nFunction: isset\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    
array_key_exists('h'$array);
echo 
"\n\nFunction: array_key_exists\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';



$array = array(
    
'a'=>1,
    
'b'=>2,
    
'c'=>3,
    
'd'=>4,
    
'e'=>5,
    
'f'=>6,
    
'g'=>7,
    
'h'=>8,
    
'i'=>9,
    
'j'=>10,
    
'k'=>11,
    
'l'=>12,
    
'm'=>13,
    
'n'=>14,
    
'o'=>15,
    
'p'=>16,
    
'q'=>17,
    
'r'=>18,
    
's'=>19,
    
't'=>20);

echo 
"\n\n------------------------\n\n";
echo 
"Array type: associative\nCount: ".count($array)."\nKey: h";

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    isset(
$array['h']);
echo 
"\n\nFunction: isset\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    
array_key_exists('h'$array);
echo 
"\n\nFunction: array_key_exists\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';



$array = array(
    
'a'=>1,
    
'b'=>2,
    
'c'=>3,
    
'd'=>4,
    
'e'=>5,
    
'f'=>6,
    
'g'=>7,
    
'h'=>8,
    
'i'=>9,
    
'j'=>10,
    
'k'=>11,
    
'l'=>12,
    
'm'=>13,
    
'n'=>14,
    
'o'=>15,
    
'p'=>16,
    
'q'=>17,
    
'r'=>18,
    
's'=>19,
    
't'=>20);

echo 
"\n\n------------------------\n\n";
echo 
"Array type: associative\nCount: ".count($array)."\nKey: gh";

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    isset(
$array['gh']);
echo 
"\n\nFunction: isset\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';

$time_start array_sum(explode(' ',microtime()));
for(
$i=0$i<$times; ++$i
    
array_key_exists('gh'$array);
echo 
"\n\nFunction: array_key_exists\nTime: ".(array_sum(explode(' ',microtime())) - $time_start).' Sec';



echo 
"\n\n\nTotal: ".(array_sum(explode(' ',microtime())) - $total_time_start).' Sec';

?>
תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
תגובה

כלי אשכול חפש באשכול זה
חפש באשכול זה:

חיפוש מתקדם
מצבי תצוגה דרג אשכול זה
דרג אשכול זה:

מזער את תיבת המידע אפשרויות משלוח הודעות
אתה לא יכול לפתוח אשכולות חדשים
אתה לא יכול להגיב לאשכולות
אתה לא יכול לצרף קבצים
אתה לא יכול לערוך את ההודעות שלך

קוד vB פעיל
קוד [IMG] פעיל
קוד HTML כבוי
מעבר לפורום



כל הזמנים המוצגים בדף זה הם לפי איזור זמן GMT +2. השעה כעת היא 00:16

הדף נוצר ב 0.09 שניות עם 12 שאילתות

הפורום מבוסס על vBulletin, גירסא 3.0.6
כל הזכויות לתוכנת הפורומים שמורות © 2024 - 2000 לחברת Jelsoft Enterprises.
כל הזכויות שמורות ל Fresh.co.il ©

צור קשר | תקנון האתר