@vitland

Большая нагрузка на процессор, что оптимизировать?

Здравствуйте.

Пишу телеграм бот на nodejs + mongodb. Он посылает сообщения с картинками и описанием по запросу, есть фильтры и сообщения не повторяются, пока не закончатся все в одной категории. Фильтры и id просмотренных хранятся в базе, в документе пользователя.

При выполнении этой функции нагрузка на процессор VPS подскакивает до 60% - 70%.

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

spoiler
function sendFilesByQuery(chatId, query) {
  User.findOne({ telegramId: chatId }).then((user) => {
    // фильтры на основе которых формируется запрос
    if (user.filter.time === 1) {
      time = { $gte: 2000 };
    }
    if (user.filter.time === 2) {
      time = { $gte: 2015 };
    }
    if (user.filter.pop === 1) {
      pop = { $lt: 71 };
    }
    if (user.filter.pop === 2) {
      pop = { $gt: 9 };
    }

    if (user.filter.time === 0) {
      delete query.year;
    }
    if (user.filter1.pop === 0) {
      delete query.viewed;
    }

    query = {
      type: query.toString(),
      viewed: pop,
      year: time,
    };

    //Поиск все подходящих документов
    File.find(query).then((files) => {
      //Формируется масссив только _id, чтобы дальше исключить повторы
      let queryfiles = files.map((element) => element._id);

      //Массив со всеми id
      let allfiles;

      //Массив с просмотренными id
      let userfiles;
      
      //Массив с отфильтрованными не просмотренными id
      let rndfile;

      switch (query) {
        case "1":
          userfiles = user.files.type1;
          allfiles = user.allfiles.type1;
          //Исключаем повторы из массива
          rndfile = queryfiles.filter((f) => !userfiles.includes(f));
          bot.sendMessage(chatId, "text");
          break;
      }

      File.findById(rndfile)
        //Восстанавливает целый  рандомный документ из id
        .skip(Math.floor(Math.random() * rndfile.length))
        .then((rndfile) => {
          bot.sendDocument(chatId, rndfile.gif);

          if (!rndfile) {
            bot.sendMessage(chatId, "text");
          }

          if (userfiles.length >= allfiles.length - 1) {
            clearfilesType(user.telegramId, query);
          }
        });
    });
  });
}
  • Вопрос задан
  • 259 просмотров
Решения вопроса 1
@vitland Автор вопроса
Спасибо за советы!
Я пока нуб и без понятия, что такое профайлинг, как логгировать запросы и их интерпритировать. И на данном этапе в таком сложно разобраться.
Пока же решил проблему изменив запрос к базе, убрал сравнение массивов. Производительность значительно подросла.

function sendFilesByQuery(chatId, query) {
  User.findOne({ telegramId: chatId }).then((user) => {
    // фильтры на основе которых формируется запрос
    if (user.filter.time === 1) {
      time = { $gte: 2000 };
    }
    if (user.filter.time === 2) {
      time = { $gte: 2015 };
    }
    if (user.filter.pop === 1) {
      pop = { $lt: 71 };
    }
    if (user.filter.pop === 2) {
      pop = { $gt: 9 };
    }

    if (user.filter.time === 0) {
      delete query.year;
    }
    if (user.filter1.pop === 0) {
      delete query.viewed;
    }

    query = {
      type: query.type.toString(),
      viewed: pop,
      year: time,
//Здесь отсеиваются просмотренные файлы
      _id: {
        $nin: watched, 
      },
    };

    File.find(query).then((file) => {
      rndfile = file[Math.floor(Math.random() * file.length)];
      let allfiles;
      let userfiles;
      switch (query.type) {
        case "1":
          userfiles = user.files1;
          allfiles = user.allfiles;
          break;
      }

      bot.sendDocument(chatId, rndfile.gif);
      if (!rndfile) {
        bot.sendMessage(chatId, "text");
      }
      if (userfiles1.length >= allfiles.length - 1) {
        clearfilesType(user.telegramId, query);
      }
    });
  });
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@mrsaa
ответ будет пальцем в небо, потому что много неизвестных:
но если в реляционных бд реализовывать фильтры, то надо думать про индексы, а как с этим в монгодб?

ну и я бы рекомендовал сначала произвести детальный профайлинг, хотя бы посмотреть какие процессы грузят, сколько ядер задействовано и остальные ресурсы.
Ответ написан
Комментировать
opium
@opium
Просто люблю качественно работать
посмотри кто грузит проц база или нода
если база залоггируй медленые запросы
если нода сделай профайлинг
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы