Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Другие языки > Go и I/O Completion Ports (Windows)


Автор: CSharpProgrammer 11.2.2015, 15:49
Добрый день.

Начал разбираться с Go и решил написать на Go простенькую утилиту для проверки ответа, который отдает сервер по заданному URL. В интеренте встречал программы, написаны на С++ с использованием технологии I/O Completion Ports (Windows), которые позволяют за пол минуты проверить около миллиона ссылок (создавая несколько тысяч параллельных соединений). Собственно вопрос возможно ли тоже самое сделать на Go?

Вот код, который я напиал на коленке, так как канал интернета у меня 1024/512 Кбит/с то проверить на 5000 соединениях не могу. Кто хорошо знаком с Go помогите разобраться с вопросом и подкоректировать код для лучшей производительности.

Код

package main

import (
    "fmt"
    "net/http"
    "bufio"
    "os"
    "sync"
    "time"
)

func main() {
    var urls chan string = make(chan string)

    // spawn n worker goroutines
    var wg sync.WaitGroup
    for i := 0; i < 20; i++ {
        wg.Add(1)
        go func() {
            for url := range urls {
                check(url)
            }
            wg.Done()
        }()
    }

    file, _ := os.Open("./urls.txt")
    defer file.Close()
    
    scanner := bufio.NewScanner(file)
    scanner.Split(bufio.ScanLines)

    for scanner.Scan() {
        urls <- scanner.Text()
    } 
    
    close(urls)

    // wait for the workers to finish
    wg.Wait()
}

func check(url string) {
    resp, err := http.Head(url)
    if err != nil {
        fmt.Println(err)
        return
    }
    
    fmt.Printf("%v:%s:%d\r\n", time.Now(), url, resp.StatusCode)
}


P.S. В *nix системах, как я понимаю, используются схожие механизмы epoll or kqueue, так что OC принципиального значения для задачи не имеет.

Автор: k0rvin 14.2.2015, 23:26
Цитата(CSharpProgrammer @  11.2.2015,  15:49 Найти цитируемый пост)
помогите разобраться с вопросом

http://www.youtube.com/watch?v=f6kdp27TYZs

Автор: k0rvin 14.2.2015, 23:56
Цитата(CSharpProgrammer @  11.2.2015,  15:49 Найти цитируемый пост)
Собственно вопрос возможно ли тоже самое сделать на Go?

Возможно: http://play.golang.org/p/Yvz0_M_Qjr

Код

package main

import (
    "bufio"
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

const chanbuf = 1000

func main() {
    var urls = make(chan string, chanbuf)
    var done = make(chan struct{}, chanbuf)
    var proc = 0
    if len(os.Args) != 2 {
        perror("Usage: " + os.Args[0] + " <file name>")
        os.Exit(1)
    }
    f, err := os.Open(os.Args[1])
    if err != nil {
        perror(err.Error())
        os.Exit(1)
    }
    defer f.Close()

    go read(urls, f)
    for url := range urls {
        proc++
        go check(done, url)
    }
    for i := 0; i < proc; i++ {
        <-done
    }
}

func perror(msg string) {
    fmt.Fprintln(os.Stderr)
}

func read(out chan string, r io.Reader) {
    scanner := bufio.NewScanner(r)
    scanner.Split(bufio.ScanLines)
    for scanner.Scan() {
        out <- scanner.Text()
    }
    close(out)
    if scanner.Err() != nil {
        perror(scanner.Err().Error())
    }
}

func check(done chan struct{}, url string) {
    resp, err := http.Head(url)
    if err != nil {
        perror(err.Error())
    }
    fmt.Print(fmt.Sprintf("%v:%s:%d\r\n", time.Now(), url, resp.StatusCode))
    done <- struct{}{}
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)