Потребление от двух каналов одновременно приводит к тому, что мои оперативные памяти занимают много времени - PullRequest
0 голосов
/ 08 июня 2019

Я довольно новичок в параллелизме, и я решил запустить несколько частей моего обработчика http в goroutines, и он начал поглощать мою оперативную память и зависал мой компьютер.

Вот что я пытаюсь сделать:

Мой обработчик имеет эти два вызова функций

qChan := cloneQuestions(currentFormView.QuestionObjects, currentForm.Id, currentForm.VersionNumber, now)

rChan := cloneRules(currentFormView.RuleObjects, currentForm.Id, currentForm.VersionNumber, now)

Оба этих вызова функций определены в файле helpers.go, и они возвращают каналы структур своим вызывающим.

Это определение функции cloneQuestions, и clonedRules следует той же схеме, что и эта

func cloneQuestions(questions []question.Model, formID string, versionNumber int, now time.Time) <-chan question.Model {
    out := make(chan question.Model)

    go func() {
        for _, currentQuestion := range questions {
            out <- getClonedQuestion(currentQuestion, formID, versionNumber, now)
        }
        close(out)
    }()

    return out
}

    func getClonedQuestion(currentQuestion question.Model, formID string, versionNumber int, now time.Time) question.Model {
    newOptionsArray := cloneQuestionOptions(currentQuestion, formID, now)


    return currentQuestion
}

cloneRules очень похож на этот

После вызова этих двух функций в моем обработчике и сохранения их возвращенных каналов в переменных qChan и rChan, как описано выше, я запускаю бесконечный цикл для одновременного потребления значений из обоих каналов и прекращаю работу цикла, как только прекращаю получать значения из обоих каналы, вот код

for {
    select {
    case clonedQuestion := <-qChan:
        insertQuestionToFormTxn := h.service.Mongo.GetAppendTxn(ctx, form.COLLECTION, currentForm.FormID, "questions", clonedQuestion.Id, clonedQuestion.Order)

        newQuestionTxn := h.service.Mongo.GetNewTxn(ctx, question.COLLECTION, clonedQuestion, clonedQuestion.Id)
        // collect all the txns in the arrray
        array = append(array, insertQuestionToFormTxn, newQuestionTxn)
    case clonedRule := <-rChan:

        newRuleTxn := h.service.Mongo.GetNewTxn(ctx, rule.COLLECTION, clonedRule, clonedRule.Id)
        // collect all the txns in the arrray
        array = append(array, insertRuleToFormTxn, newRuleTxn)
    default:
        break
    }
}

Когда я делаю запрос к этому обработчику и запускаю htop рядом, я увидел, что он начал заполнять мою оперативную память и заморозил мою машину, почему это происходит?

Ответы [ 2 ]

1 голос
/ 08 июня 2019

Как подсказывает @JimB, удалите предложение default из оператора select, так как оно вызывает замкнутый цикл, который привязывает ваш ЦП.

Опциональное значение по умолчанию для выбора позволяет неблокировать опрос каналов. В вашем случае вы хотите подождать любой элемент канала. И в большинстве случаев блокирование лучше, чем опрос.

Если вы беспокоитесь, что сервис может показаться спящим из-за блокировки, вы можете добавить канал таймера, чтобы показать живость, например,

t := time.NewTicker(time.Minute)
for {
    select {
    case i := <-ch:
        log.Println("got item:", i)
    case <-t.C:
        log.Println("I'm not dead yet!")
    }
}

детская площадка

0 голосов
/ 08 июня 2019

Трудно сказать без профилирования вашей программы или, что еще лучше, без ее отслеживания.Если вы включите трассировку, вы легко увидите, где ваш код выделяет большую часть памяти.

Но есть две вещи, которые вы можете заметить из вашей реализации:

  1. Зачем клонировать объекты?Другие горутины получают к ним доступ?В противном случае вы могли бы просто использовать объекты напрямую и избежать затрат на клонирование.
  2. Вы уверены, что вам нужны каналы и программы для обработки questions и rules объектов?Мне кажется, что в функции cloneQuestions вы не выполняете никаких операций ввода-вывода, фактически вы просто клонируете объект и отправляете его на канал.Наконец, вы берете эти объекты и добавляете их все в один фрагмент (то есть array).Таким образом, алгоритм выглядит как последовательный, и вы не получите никакого выигрыша в производительности от использования параллелизма.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...