• דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

סדר התשובות בלולאה אסינכרונית

מתוזמן נעוץ נעול הועבר תכנות
10 פוסטים 3 כותבים 109 צפיות
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
תגובה
  • תגובה כנושא
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • nigunN מנותק
    nigunN מנותק
    nigun
    כתב ב נערך לאחרונה על ידי nigun
    #1

    כמו שאמרו כאן כמה חברים שאני אצטרך די מהר להשתמש בקוד אסינכרוני
    זה הגיע יותר מהר ממה שחשבתי
    אני מנסה לבדוק איך הAPI שלי (שכתוב בPHP) מחזיק במספר קריאות במקביל (למה זה אמור בכלל לעשות בעיה , זה נושא בפני עצמו)
    אז בניתי סקריפט בגו שישלח בקשה לשרת דרך HTTP
    ועשיתי לולאה של קריאות אסינכרוניות (דהיינו שקורא לפונקציה ולא מחכה לתשובה ומפעיל את הפונקציה שוב )
    עד עכשיו הכל טוב ויפה אבל לא תמיד הקריאה הראשונה מסתיימת לפני השנייה
    ואני לא יודע מתוך התשובות שקיבלתי מה היה סדר הקריאות
    ניסיתי לכתוב שידפיס בסוף הפונקציה את המספר של הלולאה הנוכחית
    אבל תמיד זה יוצא לי בסדר הפוך (דהיינו תוצאה 2 ואז 1)
    האם אני עשיתי נכון ופשוט משום מה הקריאה השניה חוזרת לפני הראשונה או שלא הבנתי נכון איך זה עובד?
    אני יצרף פה את הקוד שאמנם כתוב בגו אבל אולי זה יעזור להבין את השאלה

    
    package main
    
    import (
        "strings"
        "os"
        "fmt"
    	"io/ioutil"
    	"net/http"
    )
    
    func postto(s int, c chan int) {
    body := strings.NewReader(`phone=0523456789&amount=3`)
    
    
    req, err := http.NewRequest("POST", "http://www.host.com/test.php", body)
    
    if err != nil {
            
    }
    
    
    
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
    }
    defer resp.Body.Close()
      contents, err := ioutil.ReadAll(resp.Body)
            if err != nil {
                fmt.Printf("%s", err)
                os.Exit(1)
            }
            fmt.Printf("%s\n", string(contents))
           fmt.Println(s)
    c <- s
        }
      func main() {
                 var b int = 3
       var a int
    	c := make(chan int)
       for a < b {
          a++
              
    
          go postto(a,c)
       } 
     x, y := <-c, <-c 
    
    	fmt.Println(x, y)
    }
    
    
      
    
    
    

    מייל: nigun@duck.com

    תגובה 1 תגובה אחרונה
    0
  • nigunN מנותק
    nigunN מנותק
    nigun
    כתב ב נערך לאחרונה על ידי
    #2

    עדכון:עכשיו הוספתי לתחילת הפונקציה

        now := time.Now()
    
          unixNano := now.UnixNano()                                                                      
             umillisec := unixNano / 1000000
    

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

     fmt.Println("(correct)Millisecond : ", umillisec) 
    

    ותוצאה היא

    OK
    2
    (correct)Millisecond :  1561995505989
    OK
    1
    (correct)Millisecond :  1561995505991
    

    OK זה התשובה מהשרת שלי
    אבל למרבה הפלא בזמן כתוב קודם את הקריאה הראשונה ובמספר הלולאה את השניה
    אז כנראה פיספסתי כאן משהו

    מייל: nigun@duck.com

    י תגובה 1 תגובה אחרונה
    0
  • י מנותק
    י מנותק
    יוסף בן שמעון
    השיב לnigun ב נערך לאחרונה על ידי יוסף בן שמעון
    #3

    @nigun

    1. אתה יכול להתפטר מהשורות המיותרות האלה
    if err != nil {
            
    }
    

    אם בהשמה תכתוב כך:

    resp, _ := http.DefaultClient.Do(req)
    
    

    במקום לכתוב err כותבים קו תחתון וזה פוטר אותך מלהשתמש במשתנה הזה.

    1. יש לך טעות בלולאה, אתה רצית 2 קריאות אבל אתה בעצם מריץ לולאה של 3 קריאות כי a מתחיל מאפס ונגמר ב 3, הסיבה שאתה לא רואה 3 תוצאות כנראה בגלל שהפונקציה main מתה לפני שהקריאה השלישית מתסיימת. תוסיף בסוף הפונקציה השהייה כזו:
    time.Sleep(10 * time.Second)
    

    ותבדוק אם זה משנה את התמונה

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

    nigunN תגובה 1 תגובה אחרונה
    4
  • nigunN מנותק
    nigunN מנותק
    nigun
    השיב ליוסף בן שמעון ב נערך לאחרונה על ידי nigun
    #4

    @יוסף-בן-שמעון

    1. הורדתי את השורות של הerr (זה לא הבעיה אבל הקוד יותר נקי)
    2. הלולאה רצה 2 פעמים כי התנאי הוא a<2 ולא a<=2
      לצורך ביטחון הגדרתי Sleep ל10 שניות
      ועדיין מחזיר רק שתי קריאות

    לגופו של עניין אין לי בעיה שיחזרו בסדר שונה
    אבל אני רוצה לדעת מה הסדר של הקריאות

    המשתנה של זמן לכאורה אמור להצביע על איזה קריאה נעשתה קודם
    כי יש הבדל של חלקיק שנייה בין קריאה לקריאה
    וגם המשתנה a אמור להיות בלולאה הראשונה 1 ובשניה 2
    אבל זה עובד בדיוק הפוך משום מה

    עכשיו הרצי את הקוד פעמים וכל פעם חזר בסדר שונה
    אין לי בעיה עם זה אבל מה קרה בכל פעם
    שים לב שגם המשתנים x y מושפעים מסדר התשובות (כי הם מקבלים את הערך מs)

    root@scw-vibrant-bhabha:~#  go run /root/go/src/curl/main2.go
    OK
    2
    (correct)Millisecond :  1562049086784
    OK
    1
    (correct)Millisecond :  1562049086787
    2 1
    root@scw-vibrant-bhabha:~# go run /root/go/src/curl/main2.go
    OK
    1
    (correct)Millisecond :  1562049526808
    OK
    2
    (correct)Millisecond :  1562049526807
    1 2
    

    מייל: nigun@duck.com

    yossizY תגובה 1 תגובה אחרונה
    0
  • yossizY מנותק
    yossizY מנותק
    yossiz
    השיב לnigun ב נערך לאחרונה על ידי yossiz
    #5

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

    אתה כן יכול להניח שה-scheduler לא סתם משחק משחקים איתך בשביל הכיף... ואם תעמיק בקוד של ה-scheduler תוכל להבין מה קורה, אבל אסור לך לסמוך על סדר מסויים.

    פעם עניתי על שאלה דומה, וניסיתי לנתח איך ה-scheduler מבצע תוכנה מסויימת עיין כאן. אולי התשובה שם יעזור לך להבין מה קורה פה.

    (בלי להכיר כל כך את השפה, אני די בטוח שבמקרה שחייבים סדר מסויים יש מבנים בתוך השפה שתוכל להשתמש בהם כדי לסנכרן סדר הפעולות, אבל הרי לא עשית את זה)

    📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

    nigunN תגובה 1 תגובה אחרונה
    4
  • nigunN מנותק
    nigunN מנותק
    nigun
    השיב לyossiz ב נערך לאחרונה על ידי nigun
    #6

    עכשיו ניסיתי לוותר לגמרי על האזנה לערוץ

     x, y := <-c, <-c 
    
    	fmt.Println(x, y)
    

    ולהשתמש רק בפונקצית שינה
    ועכשיו המספר לולאה כן לפי הסדר הזמנים של הקריאות
    הנה התשובות שקיבלתי
    הראשון זה בלי Sleep
    והשני עם Sleep ובלי האזנה לערוץ

    root@scw-vibrant-bhabha:~# go run /root/go/src/curl/main2.go
    OK
    1
    (correct)Millisecond :  1562065593494
    OK
    2
    (correct)Millisecond :  1562065593491
    1 2
    root@scw-vibrant-bhabha:~# go run /root/go/src/curl/main2.go
    OK
    2
    (correct)Millisecond :  1562065640343
    OK
    1
    (correct)Millisecond :  1562065640341
    

    זה נראה שבשני הפעמים הקריאה השניה חוזרת לפני הראשונה
    אבל לפחות בפעם השניה כתוב לי שזה הקריאה השניה ולא הראשונה
    וזה נראה נכון כי 1562065640343 זה אחרי 1562065640341
    (אני מקווה שאני כותב ברור ולא קשקושים לא מובנים)

    מייל: nigun@duck.com

    yossizY תגובה 1 תגובה אחרונה
    0
  • yossizY מנותק
    yossizY מנותק
    yossiz
    השיב לnigun ב נערך לאחרונה על ידי
    #7

    @nigun לא הבנתי לְמֵה אתה חותר.
    אם אתה רוצה להדפיס שורה ולדעת איזה פונקציה כותב את זה, תדפיס באותה שורה גם את המספר של הקריאה.
    לגבי סדר הפעולות, אתה יכול לסמוך על זה שהסדר בתוך הפונקציה נשמר, אבל לא תוכל לסמוך על שום סדר בין-פונקציאלי.
    אאל"ט, גם מילת המפתח go, לא מריץ את הפונקציה, אלא שם את הפונקציה בתור להרצה מתישהו. אתה יכול לסמוך שהקריאה הראשונה הושם בתור לפני השניה, אבל אתה לא יכול לסמוך על שסביבת ההרצה החליטה להתחיל את הרצת הראשונה לפני השניה.

    📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

    nigunN תגובה 1 תגובה אחרונה
    1
  • nigunN מנותק
    nigunN מנותק
    nigun
    השיב לyossiz ב נערך לאחרונה על ידי nigun
    #8

    @yossiz
    אני רוצה לדעת את מספר קריאה
    ומשום מה זה לא נראה שזה כותב את המספר קריאה האמיתי
    הדרך שאני מנסה לבדוק האם זה המספר קריאה הנכון
    אני מדפיס בנוסף את זמן הקריאה
    ומשום מה זה כותב קריאה 1 בשניה 343.. וקריאה 2 בשניה 341...
    וכל זה קורה רק אם אני מחכה לתשובה מהערוץ בסוף הסקריפט
    אבל אם אני סתם מחכה בסוף הסקריפט 10 שניות
    אז יוצא לי קריאה 1 בשניה 341.. וקריאה 2 בשניה 343...
    אם זה היה חד פעמי הייתי אומר שבדיוק ככה יצא שלפעמים הקריאה הראשונה מתחילה אחרי השניה
    אבל זה כל הזמן חוזר בסדר הזה (גם אם הקריאה השניה חוזרת ראשונה וגם להיפך)

    אולי אם אני ישים את בשורה אחת זה יהיה יותר מובן

    OK
    (correct)Millisecond :  1562077651112 at 1
    OK
    (correct)Millisecond :  1562077651110 at 2
    

    מייל: nigun@duck.com

    yossizY תגובה 1 תגובה אחרונה
    0
  • yossizY מנותק
    yossizY מנותק
    yossiz
    השיב לnigun ב נערך לאחרונה על ידי yossiz
    #9

    @nigun אמר בסדר התשובות בלולאה אסינכרונית:

    ומשום מה זה לא נראה שזה כותב את המספר קריאה האמיתי

    במושכל ראשון אין כל סיבה לחשוש שהפלט לא נכון.

    הדרך שאני מנסה לבדוק האם זה המספר קריאה הנכון
    אני מדפיס בנוסף את זמן הקריאה

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

    אני יודע שלא עניתי על שאלתך "למה זה רץ בסדר זה?" אבל אופתע אם יש תשובה פשוטה לשאלה הזאת.
    תשובה חלקית יכולה להיות שהחלטות ה-scheduler מושפעות מהצפי שלו לגבי איזה goroutine ישפיע על הזרימה החלקה של המשך הקוד. כאשר אתה קורא sleep אז סביבת ההרצה "יודע" שאתה לא זמין לעוד הרבה זמן, וזה משפיע על החלטותיה לגבי על איזה ליבה ואיזה thread לתזמן את ה-goroutines שמחכים בתור. וזה משפיע על התזמון של ההרצות.

    יש לך פה בלוג ב-3 המשכים על נושא התזמון בגו.
    https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part1.html
    https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part2.html
    https://www.ardanlabs.com/blog/2018/12/scheduling-in-go-part3.html

    אחרי זה, תוכל לקרוא את קוד המקור של רכיב ה-scheduler פה: https://golang.org/src/runtime/proc.go (להתראות בעוד חודש...) 🙂

    📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

    nigunN תגובה 1 תגובה אחרונה
    3
  • nigunN מנותק
    nigunN מנותק
    nigun
    השיב לyossiz ב נערך לאחרונה על ידי
    #10

    @yossiz
    מצאתי כאן הסבר למה זה רנדומאלי
    אבל למען האמת לא הבנתי את ההסברים

    מייל: nigun@duck.com

    תגובה 1 תגובה אחרונה
    1

  • התחברות

  • אין לך חשבון עדיין? הרשמה

  • התחברו או הירשמו כדי לחפש.
  • פוסט ראשון
    פוסט אחרון
0
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
  • התחברות

  • אין לך חשבון עדיין? הרשמה

  • התחברו או הירשמו כדי לחפש.