Как разбить запросы с большим количеством ЦП в Google App Engine?

Приведу пример запроса, для которого я не могу понять, что еще делать:

Приложение представляет собой счет / статистика боулинга. Когда кто-то вводит свои баллы в расширенном режиме, вычисляется ряд характеристик, а также их баллы. Данные моделируются как:

Игра - участники, такие как имя, пользователь, ссылка на боулинг, счет Кадр - попадания кеглей для каждого шара, логические списки, для которых кегли были сбиты на каждом шаре, информация о траектории мяча (стойка, цель, куда он на самом деле попал), счет на этот кадр и т. д. GameStats - хранит рассчитанную статистику для всей игры, которая может быть объединена с другой игровой статистикой по мере необходимости для отображения статистики по группам игр.

Пример этой информации на практике можно найти в здесь.

Когда игра завершена и кадр обновлен, я должен обновить игру, кадр, каждый кадр после него и, возможно, некоторые до него (чтобы убедиться, что их результаты верны) и статистику. Эта операция всегда помечает монитор ЦП. Даже если игра не завершена и статистику вычислять не нужно, баллы и тому подобное необходимо обновить, чтобы показать пользователю прогресс в реальном времени, и поэтому они также помечаются. Среднее время процессора для этого обработчика составляет более 7000 мциклов, и он даже не отображает представление. Большинство людей ставят от 3 до 4 игр за серию - если они вводят свои результаты в реальном времени на дорожках, это примерно 1 запрос каждые 2–4 минуты, но если они записывают все и вводят позже, получается 30-40 игр. эти запросы делаются подряд.


Согласно запросу, модель данных для важных классов:

class Stats(db.Model):
  version = db.IntegerProperty(default=1)
  first_balls=db.IntegerProperty(default=0)
  pocket_tracked=db.IntegerProperty(default=0)
  pocket=db.IntegerProperty(default=0)
  strike=db.IntegerProperty(default=0)
  carry=db.IntegerProperty(default=0)
  double=db.IntegerProperty(default=0)
  double_tries=db.IntegerProperty(default=0)
  target_hit=db.IntegerProperty(default=0)
  target_missed_left=db.IntegerProperty(default=0)
  target_missed_right=db.IntegerProperty(default=0)
  target_missed=db.FloatProperty(default=0.0)
  first_count=db.IntegerProperty(default=0)
  first_count_miss=db.IntegerProperty(default=0)

  second_balls=db.IntegerProperty(default=0)
  spare=db.IntegerProperty(default=0)
  single=db.IntegerProperty(default=0)
  single_made=db.IntegerProperty(default=0)
  multi=db.IntegerProperty(default=0)
  multi_made=db.IntegerProperty(default=0)
  split=db.IntegerProperty(default=0)
  split_made=db.IntegerProperty(default=0)

class Game(db.Model):
  version = db.IntegerProperty(default=3)
  user = db.UserProperty(required=True)
  series = db.ReferenceProperty(Series)
  score = db.IntegerProperty()
  game_number = db.IntegerProperty()
  pair = db.StringProperty()
  notes = db.TextProperty()
  simple_entry_mode = db.BooleanProperty(default=False)
  stats = db.ReferenceProperty(Stats)
  complete = db.BooleanProperty(default=False)

class Frame(db.Model):
  version = db.IntegerProperty(default=1)
  user = db.UserProperty()
  game = db.ReferenceProperty(Game, required=True)
  frame_number = db.IntegerProperty(required=True)
  first_count = db.IntegerProperty(required=True)
  second_count = db.IntegerProperty()
  total_count = db.IntegerProperty()
  score = db.IntegerProperty()
  ball = db.ReferenceProperty(Ball)
  stance = db.FloatProperty()
  target = db.FloatProperty()
  actual = db.FloatProperty()
  slide = db.FloatProperty()
  breakpoint = db.FloatProperty()
  pocket = db.BooleanProperty()
  pocket_type = db.StringProperty()
  notes = db.TextProperty()
  first_pinfall = db.ListProperty(bool)
  second_pinfall = db.ListProperty(bool)
  split = db.BooleanProperty(default=False)
За пределами сигналов Angular: Сигналы и пользовательские стратегии рендеринга
За пределами сигналов Angular: Сигналы и пользовательские стратегии рендеринга
TL;DR: Angular Signals может облегчить отслеживание всех выражений в представлении (Component или EmbeddedView) и планирование пользовательских...
Sniper-CSS, избегайте неиспользуемых стилей
Sniper-CSS, избегайте неиспользуемых стилей
Это краткое руководство, в котором я хочу поделиться тем, как я перешел от 212 кБ CSS к 32,1 кБ (сокращение кода на 84,91%), по-прежнему используя...
1
0
1 000
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Несколько предложений:

  • Вы можете хранить статистику кадров как часть той же сущности, что и игра, вместо того, чтобы иметь отдельную сущность для каждой, сохранив ее как список битовых полей (хранящихся в целых числах) для контактов, стоящих в конце каждой половины. рама, например. Дайте мне знать, если вы хотите получить более подробную информацию о том, как это будет реализовано.
  • В противном случае вы можете вычислить некоторые из более взаимосвязанных статистических данных при выборке. Например, подсчет очков на данный момент должен быть простым, если у вас сразу загружена вся игра, а это значит, что вам не придется обновлять несколько кадров при каждом запросе.
  • Мы можем быть более полезными, если вы покажете нам свою модель данных. :)

Я думал об использовании идеи битового поля для булавок, но это не очень удобно, по крайней мере, в GAE. Например, я хочу захватить все рамки, на которых я оставил некоторую форму размытия (шпилька, 2 булавки и 10 булавки стоят, а 3, 5 и 9 - нет).

Chris Marasti-Georg 30.09.2008 20:36

Вы хотите получить все кадры из одной игры, соответствующие этим критериям, или все кадры из всех игр? Если бы первое, то линейный поиск был бы проще.

Nick Johnson 01.10.2008 12:40

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

Nick Johnson 01.10.2008 12:50

Я хотел бы найти кадры из всех игр (для пользователя) или определенного подмножества игр. В объекте Frame только 4 свойства могут быть вычислены из других, и они не обязательно тривиальны (например, is_split). Я думал, что GAE поощряет хранение большого количества данных?

Chris Marasti-Georg 01.10.2008 15:15

Это так, но в виде множества объектов, организованных таким образом, что вы должны касаться как можно меньшего числа в запросе. Моя предложенная стратегия заключалась в том, чтобы хранить только все, что вам нужно проиндексировать, и все, что вам нужно для восстановления полного набора данных, а также все, что значительно дорого для расчета.

Nick Johnson 01.10.2008 15:26

Причина, по которой я в итоге добавил класс статистики, заключалась в том, что когда у меня была лига с 16 неделями, каждая из которых имела 4 игры, вычисление статистики для всего этого приводило к чрезмерной загрузке процессора. Хммм ... Может мне просто нужно подождать увеличения платной квоты? Или посмотрите другой хостинг?

Chris Marasti-Georg 01.10.2008 17:22

Или разбейте его на более мелкие запросы - не пытайтесь обрабатывать 64 игры за один запрос.

Nick Johnson 02.10.2008 13:11

Какие-нибудь советы о том, как этого добиться?

Chris Marasti-Georg 02.10.2008 17:57

Если ваше приложение AJAX-y, оно может отправлять меньший набор игр в каждом запросе - например, отправляя их, когда пользователь вводит их.

Nick Johnson 02.10.2008 18:39

Другие вопросы по теме