Optimisations (#174)

* removed all the things causing slow times on data

* fixup look sharp

* use ujson

* bep
This commit is contained in:
Paul Hallett 2016-04-30 13:02:27 +01:00
parent 5b94cff6c8
commit 422d98fff2
7 changed files with 16 additions and 244 deletions

View file

@ -95,6 +95,7 @@ DATABASES = {
'PASSWORD': 'pokeapi',
'HOST': 'localhost',
'PORT': '',
'CONN_MAX_AGE': 30
}
}
@ -103,10 +104,6 @@ CACHES = {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'TIMEOUT': 30
},
'resources': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'TIMEOUT': 360
}
}
SECRET_KEY = os.environ.get(
@ -148,10 +145,10 @@ CORS_URLS_REGEX = r'^/api/.*$'
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'drf_ujson.renderers.UJSONRenderer',
),
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
'drf_ujson.renderers.UJSONRenderer',
),
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',

View file

@ -10,224 +10,10 @@ from hits.models import ResourceView
import stripe
from pokemon_v2.models import * # NOQA
def _total_site_data():
"""
Compute the total count of objects on the site
Using count() is drastically cheaper than len(objects.all())
"""
# v2 Sorry for the brute force. Theres probably a better way to do this.
data = dict(
abilities=Ability.objects.count(),
abilitie_names=AbilityName.objects.count(),
abilitie_effect_texts=AbilityEffectText.objects.count(),
abilities_flavor_texts=AbilityFlavorText.objects.count(),
abilities_changes=AbilityChange.objects.count(),
abilities_change_effect_texts=AbilityChangeEffectText.objects.count(),
berries=Berry.objects.count(),
berry_flavors=BerryFlavor.objects.count(),
berry_firmnesses=BerryFirmness.objects.count(),
berry_firmness_names=BerryFirmnessName.objects.count(),
characteristics=Characteristic.objects.count(),
characteristic_descriptions=CharacteristicDescription.objects.count(),
contest_combos=ContestCombo.objects.count(),
contest_types=ContestType.objects.count(),
contest_type_names=ContestTypeName.objects.count(),
contest_effects=ContestEffect.objects.count(),
contest_effect_texts=ContestEffectEffectText.objects.count(),
contest_effect_flavor_texts=ContestEffectFlavorText.objects.count(),
egg_groups=EggGroup.objects.count(),
egg_group_names=EggGroupName.objects.count(),
encounter_methods=EncounterMethod.objects.count(),
encounter_method_names=EncounterMethodName.objects.count(),
encounter_conditions=EncounterCondition.objects.count(),
encounter_condition_names=EncounterConditionName.objects.count(),
encounter_condition_values=EncounterConditionValue.objects.count(),
encounter_condition_value_names=EncounterConditionValueName.objects.count(),
encounter_condition_value_maps=EncounterConditionValueMap.objects.count(),
encounter_slots=EncounterSlot.objects.count(),
encounters=Encounter.objects.count(),
evolution_chains=EvolutionChain.objects.count(),
evolution_triggers=EvolutionTrigger.objects.count(),
evolution_trigger_names=EvolutionTriggerName.objects.count(),
experiences=Experience.objects.count(),
generations=Generation.objects.count(),
generation_names=GenerationName.objects.count(),
genders=Gender.objects.count(),
growth_rates=GrowthRate.objects.count(),
growth_rate_descriptions=GrowthRateDescription.objects.count(),
items=Item.objects.count(),
item_names=ItemName.objects.count(),
item_effect_texts=ItemEffectText.objects.count(),
item_categories=ItemCategory.objects.count(),
item_category_names=ItemCategoryName.objects.count(),
item_attributes=ItemAttribute.objects.count(),
item_attribute_maps=ItemAttributeMap.objects.count(),
item_attribute_descriptions=ItemAttributeDescription.objects.count(),
item_flavor_texts=ItemFlavorText.objects.count(),
item_fling_effects=ItemFlingEffect.objects.count(),
item_fling_effect_effect_texts=ItemFlingEffectEffectText.objects.count(),
item_pockets=ItemPocket.objects.count(),
item_pocket_names=ItemPocketName.objects.count(),
item_game_indexes=ItemGameIndex.objects.count(),
languages=Language.objects.count(),
language_names=LanguageName.objects.count(),
locations=Location.objects.count(),
location_game_indexes=LocationGameIndex.objects.count(),
location_names=LocationName.objects.count(),
location_areas=LocationArea.objects.count(),
location_area_names=LocationAreaName.objects.count(),
location_area_encounter_rates=LocationAreaEncounterRate.objects.count(),
machines=Machine.objects.count(),
moves=Move.objects.count(),
move_names=MoveName.objects.count(),
move_changes=MoveChange.objects.count(),
move_flavor_text=MoveFlavorText.objects.count(),
move_effects=MoveEffect.objects.count(),
move_effect_changes=MoveEffectChange.objects.count(),
move_effect_change_effect_texts=MoveEffectChangeEffectText.objects.count(),
move_effect_effect_texts=MoveEffectEffectText.objects.count(),
move_attributes=MoveAttribute.objects.count(),
move_attribute_names=MoveAttributeName.objects.count(),
move_attribute_maps=MoveAttributeMap.objects.count(),
move_attribute_descriptions=MoveAttributeDescription.objects.count(),
move_metas=MoveMeta.objects.count(),
move_ailments=MoveMetaAilment.objects.count(),
move_ailment_names=MoveMetaAilmentName.objects.count(),
move_battle_styles=MoveBattleStyle.objects.count(),
move_battle_style_names=MoveBattleStyleName.objects.count(),
move_categories=MoveMetaCategory.objects.count(),
move_damage_classes=MoveDamageClass.objects.count(),
move_damage_class_descriptions=MoveDamageClassDescription.objects.count(),
move_learn_methods=MoveLearnMethod.objects.count(),
move_learn_method_names=MoveLearnMethodName.objects.count(),
move_targets=MoveTarget.objects.count(),
move_target_descriptions=MoveTargetDescription.objects.count(),
move_state_changes=MoveMetaStatChange.objects.count(),
natures=Nature.objects.count(),
nature_names=NatureName.objects.count(),
nature_pokeathlon_stats=NaturePokeathlonStat.objects.count(),
nature_battle_style_preference=NatureBattleStylePreference.objects.count(),
pal_park_areas=PalParkArea.objects.count(),
pal_park_area_names=PalParkAreaName.objects.count(),
pal_parks=PalPark.objects.count(),
pokeathlon_stat_names=PokeathlonStatName.objects.count(),
pokeathlon_stats=PokeathlonStat.objects.count(),
pokedexes=PokedexVersionGroup.objects.count(),
pokedex_descriptions=PokedexDescription.objects.count(),
pokedex_version_groups=PokedexVersionGroup.objects.count(),
pokemon=Pokemon.objects.count(),
pokemon_abilities=PokemonAbility.objects.count(),
pokemon_colors=PokemonColor.objects.count(),
pokemon_names=PokemonColorName.objects.count(),
pokemon_dex_numbers=PokemonDexNumber.objects.count(),
pokemon_egg_groups=PokemonEggGroup.objects.count(),
pokemon_evolutions=PokemonEvolution.objects.count(),
pokemon_forms=PokemonForm.objects.count(),
pokemon_form_names=PokemonFormName.objects.count(),
pokemon_form_generations=PokemonFormGeneration.objects.count(),
pokemon_game_indices=PokemonGameIndex.objects.count(),
pokemon_habitats=PokemonHabitat.objects.count(),
pokemon_habitat_names=PokemonHabitatName.objects.count(),
pokemon_items=PokemonItem.objects.count(),
pokemon_moves=PokemonMove.objects.count(),
pokemon_shapes=PokemonShape.objects.count(),
pokemon_shape_names=PokemonShapeName.objects.count(),
pokemon_species=PokemonSpecies.objects.count(),
pokemon_species_names=PokemonSpeciesName.objects.count(),
pokemon_descriptions=PokemonSpeciesDescription.objects.count(),
pokemon_flavor_texts=PokemonSpeciesFlavorText.objects.count(),
pokemon_stat=PokemonStat.objects.count(),
pokemon_type=PokemonType.objects.count(),
regions=Region.objects.count(),
region_names=RegionName.objects.count(),
stats=Stat.objects.count(),
stat_names=StatName.objects.count(),
super_contest_effects=SuperContestEffect.objects.count(),
super_contest_combos=SuperContestCombo.objects.count(),
super_contest_effect_flavor_texts=SuperContestEffectFlavorText.objects.count(),
types=Type.objects.count(),
type_names=TypeName.objects.count(),
type_game_indices=TypeGameIndex.objects.count(),
type_efficacy=TypeEfficacy.objects.count(),
versions=Version.objects.count(),
version_names=VersionName.objects.count(),
version_groups=VersionGroup.objects.count(),
version_group_move_learn_methods=VersionGroupMoveLearnMethod.objects.count(),
version_group_regions=VersionGroupRegion.objects.count(),
)
lines = 0
for i in data.iteritems():
lines += i[1]
resources = 0
resources += data['abilities']
resources += data['berries']
resources += data['berry_flavors']
resources += data['berry_firmnesses']
resources += data['characteristics']
resources += data['contest_types']
resources += data['contest_effects']
resources += data['egg_groups']
resources += data['encounter_methods']
resources += data['encounter_conditions']
resources += data['encounter_condition_values']
resources += data['evolution_chains']
resources += data['evolution_triggers']
resources += data['generations']
resources += data['genders']
resources += data['growth_rates']
resources += data['items']
resources += data['item_attributes']
resources += data['item_categories']
resources += data['item_fling_effects']
resources += data['item_pockets']
resources += data['languages']
resources += data['locations']
resources += data['location_areas']
resources += data['moves']
resources += data['move_ailments']
resources += data['move_categories']
resources += data['move_battle_styles']
resources += data['move_damage_classes']
resources += data['move_learn_methods']
resources += data['move_targets']
resources += data['natures']
resources += data['pal_park_areas']
resources += data['pokedexes']
resources += data['pokemon']
resources += data['pokemon_colors']
resources += data['pokemon_forms']
resources += data['pokemon_habitats']
resources += data['pokemon_shapes']
resources += data['pokemon_species']
resources += data['pokeathlon_stats']
resources += data['regions']
resources += data['stats']
resources += data['super_contest_effects']
resources += data['types']
resources += data['versions']
resources += data['version_groups']
data['total_lines'] = lines
data['total_resources'] = resources
return data
def about(request):
site_data = _total_site_data()
total_views = ResourceView.objects.total_count()
total_v1_views = ResourceView.objects.total_count(version=1)
total_v2_views = ResourceView.objects.total_count(version=2)
average_day = int(round(total_views / ResourceView.objects.count()))
@ -235,10 +21,7 @@ def about(request):
'pages/about.html',
{
'total': total_views,
'total_v1': total_v1_views,
'total_v2': total_v2_views,
'average_day': average_day,
'site_data': site_data,
},
context_instance=RequestContext(request)
)

View file

@ -3,7 +3,7 @@ from django.db import models
from datetime import date
class ViewManager(models.Manager):
class ResourceViewManager(models.Manager):
def increment_view_count(self, version):
@ -14,30 +14,21 @@ class ViewManager(models.Manager):
view.count = view.count + 1
print view
view.save()
def total_count(self, version=0):
if version:
objects = ResourceView.objects.filter(version=version)
else:
objects = ResourceView.objects.all()
all_hits = ResourceView.objects.all().values_list('count', flat=True)
t = 0
for v in objects:
t += v.count
return t
return sum(all_hits)
class ResourceView(models.Model):
objects = ViewManager()
objects = ResourceViewManager()
def __unicode__(self):
return str(self.date) + ' - ' + str(self.count)
return '{} - {}'.format(str(self.date), str(self.count))
count = models.IntegerField(max_length=1000, default=0)
version = models.IntegerField(max_length=1, default=1)

View file

@ -9,7 +9,7 @@ from hits.models import ResourceView
###########################
# BEHAVOIR ABSTRACTIONS #
# BEHAVIOR ABSTRACTIONS #
###########################
class ListOrDetailSerialRelation():

View file

@ -2974,7 +2974,7 @@ class PokedexDetailSerializer(serializers.ModelSerializer):
def get_pokedex_entries(self, obj):
results = PokemonDexNumber.objects.order_by('pokedex_number').filter(pokedex=obj)
results = PokemonDexNumber.objects.filter(pokedex=obj).order_by('pokedex_number')
serializer = PokemonDexNumberSerializer(results, many=True, context=self.context)
data = serializer.data

View file

@ -10,6 +10,7 @@ django-imagekit==3.2.4
django-tastypie==0.12.1
django-markdown-deux==1.0.5
djangorestframework>=3.1.0
drf-ujson==1.2.0
gunicorn==0.17.0
markdown2==2.3.0
mimeparse==0.1.3

View file

@ -45,7 +45,7 @@
</p>
<div class="well">
<p>
This website provides a RESTful API interface to <b>{{ site_data.total_resources|intcomma }}</b> highly detailed objects built from <b>{{ site_data.total_lines|intcomma }}</b> lines of data
This website provides a RESTful API interface to highly detailed objects built from thousands of lines of data
related to <a href="https://en.wikipedia.org/wiki/Pokemon">Pokémon</a>. We specifically cover the video game franchise, though we'd like to cover the card game too. Using this website you can consume information on Pokémon, their moves, abilities, types, egg groups and much much more.
</p>
</div>
@ -57,7 +57,7 @@
This is probably worth clearing up very quickly for those who don't know.<br />
An API (Application Programming Interface) is a set of interfaces (in this case, url links)
that are publicly available, that allow developers to interact with an application.<br />
In this instance; the application is a database of <b>{{ site_data.total_items|intcomma }}</b> pokemon-related objects.
In this instance; the application is a database of thousands oc pokemon-related objects.
</p>
</div>
<p class="lead">