2013-04-27 2 views
1

Я придумал простой пример, который вставляет 10 миллионов записей в mongodb. Я начал работать, последовательно работая. Затем я посмотрел, как делать параллелизм, и нашел гортанов. Это похоже на то, что я хочу, но это не так, как я ожидал. Я реализовал WaitGroup, чтобы заблокировать запуск программы до того, как все goroutines были завершены, но у меня все еще есть проблема.Как работают гортины, и они умирают, когда заканчивается главный процесс?

Итак, я начну с того, что происходит, затем покажите код. Когда я запускаю код без goroutine, все 10 миллионов записей вставляются в mongodb в порядке. Однако, когда я добавляю горутин, вводится некоторая неопределенная сумма. Обычно около 8500 дают или берут пару сотен. Я проверил журнал mongodb, чтобы узнать, есть ли у него проблемы, и ничего не появляется. Поэтому я не уверен, что это возможно, просто не регистрируется. В любом случае, вот код:

(Боковое примечание: я делаю по 1 записи за раз, но я разделил ее на метод, чтобы я мог тестировать несколько записей за раз в будущем .. just haven «т придумали, как это сделать с MongoDB еще.)

package main 

import (
    "fmt" 
    "labix.org/v2/mgo" 
    "strconv" 
    "time" 
    "sync" 
) 

// structs 
type Reading struct { 
    Id string 
    Name string 
} 

var waitGroup sync.WaitGroup 

// methods 
func main() { 
    // Setup timer 
    startTime := time.Now() 

    // Setup collection 
    collection := getCollection("test", "readings") 
    fmt.Println("collection complete: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64)) 

    // Setup readings 
    readings := prepareReadings() 
    fmt.Println("readings prepared: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64)) 

    // Insert readings 
    for i := 1; i <= 1000000; i++ { 
    waitGroup.Add(1) 
    go insertReadings(collection, readings) 

    // fmt.Print(".") 

    if i % 1000 == 0 { 
     fmt.Println("1000 readings queued for insert: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64)) 
    } 
    } 
    waitGroup.Wait() 

    fmt.Println("all readings inserted: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64)) 
} 

func getCollection(databaseName string, tableName string) *mgo.Collection { 
    session, err := mgo.Dial("localhost") 

    if err != nil { 
    // panic(err) 
    fmt.Println("error getCollection:", err) 
    } 

    // defer session.Close() 

    // Optional. Switch the session to a monotonic behavior. 
    // session.SetMode(mgo.Monotonic, true) 

    collection := session.DB(databaseName).C(tableName) 

    return collection 
} 

func insertReadings(collection *mgo.Collection, readings []Reading) { 
    err := collection.Insert(readings) 

    if err != nil { 
    // panic(err) 
    fmt.Println("error insertReadings:", err) 
    } 

    waitGroup.Done() 
} 

func prepareReadings() []Reading { 
    var readings []Reading 
    for i := 1; i <= 1; i++ { 
    readings = append(readings, Reading{Name: "Thing"}) 
    } 

    return readings 
} 
+1

Я вижу, что код, который вы опубликовали, имеет goroutines. Не могли бы вы также опубликовать код, который работает, чтобы мы могли точно видеть, что вы изменили? Или еще лучше, добавьте комментарии рядом с строками, которые вы изменили. Всегда полезно иметь рабочий пример и сравнивать его с нерабочим примером при отладке. Информация о том, что сработало для вас, важна для понимания этого. –

ответ

0

С тех пор я обнаружил, что это вопрос соединений. Драйвер для mongodb не стал пузыряться в том, что он не может получить соединение. Он не смог получить соединение из-за того, что на сервере, создаваемом на сервере, превышен предел maxfiles.

5

Program execution

полная программа создается путем объединения единый unimported пакет назвал main пакет со всеми пакетами импортирует , транзитивно. Пакет main должен иметь имя пакета main и , объявить функцию main, которая не принимает аргументов и возвращает значение .

func main() { … } 

Выполнение программы начинается с инициализации main пакет, а затем вызова функции main. Когда функция main возвращается, программа завершает работу. Он не ждет других (не main) goroutines до завершен.

Вы не предоставили нам простой, сжатый, компилируемый и исполняемый пример вашей проблемы. Вот урезанная версия вашего кода, которая работает.

package main 

import (
    "fmt" 
    "strconv" 
    "sync" 
    "time" 
) 

// structs 
type Reading struct { 
    Id string 
    Name string 
} 

var waitGroup sync.WaitGroup 

func main() { 
    // Setup timer 
    startTime := time.Now() 

    // Setup readings 
    readings := prepareReadings() 
    fmt.Println("readings prepared: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64)) 

    // Insert readings 
    for i := 1; i <= 1000000; i++ { 
     waitGroup.Add(1) 
     go insertReadings(readings) 

     // fmt.Print(".") 

     if i%100000 == 0 { 
      fmt.Println("100000 readings queued for insert: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64)) 
     } 
    } 
    waitGroup.Wait() 

    fmt.Println("all readings inserted: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64)) 
} 

func insertReadings(readings []Reading) { 
    waitGroup.Done() 
} 

func prepareReadings() []Reading { 
    var readings []Reading 
    for i := 1; i <= 1; i++ { 
     readings = append(readings, Reading{Name: "Thing"}) 
    } 
    return readings 
} 

Выход:

readings prepared: 0.00 
100000 readings queued for insert: 0.49 
100000 readings queued for insert: 1.12 
100000 readings queued for insert: 1.62 
100000 readings queued for insert: 2.54 
100000 readings queued for insert: 3.05 
100000 readings queued for insert: 3.56 
100000 readings queued for insert: 4.06 
100000 readings queued for insert: 5.57 
100000 readings queued for insert: 7.15 
100000 readings queued for insert: 8.78 
all readings inserted: 34.76 

Теперь построить программу резервного копирования, сдельная по-части, и увидеть, где он начинает терпеть неудачу.

+0

Код компилируется, запускается, вам нужен экземпляр mongodb. Я получаю то же сообщение. Опять же проблема заключается в том, что она фактически не вставляет показания. – Altonymous

Смежные вопросы