唐纳德·克努特(DonaldKnuth)曾经说过:“不成熟的优化方案是万恶之源。”然而,任何一个承受高负载的成熟项目都不可避免地需要进行优化。在本文中,我想谈谈优化Web项目代码的五种常用方法。虽然本文是以Django为例,但其他框架和语言的优化原则也是类似的。通过使用这些优化方法,文中例程的查询响应时间从原来的77秒减少到了3.7秒。
?
本文用到的例程是从一个我曾经使用过的真实项目改编而来的,是性能优化技巧的典范。假如你想自己尝试着进行优化,可以在GitHub上获取优化前的初始代码,并跟着下文做相应的修改。我使用的是Python2,因为一些第三方软件包还不支持Python3。
?
示例代码介绍
?
这个Web项目只是简单地跟踪每个地区的房产价格。因此,只有两种模型:
#houses/models.pyfromutils.hashimportHasherclassHashableModel(models.Model):"""Provideahashpropertyformodels."""classMeta:
abstract=True@propertydefhash(self):
returnHasher.from_model(self)classCountry(HashableModel):"""Representacountryinwhichthehouseispositioned."""name=models.CharField(max_length=30)def__unicode__(self):
returnself.nameclassHouse(HashableModel):"""Representahousewithitscharacteristics."""#Relationscountry=models.ForeignKey(Country,related_name='houses')#Attributesaddress=models.CharField(max_length=255)sq_meters=models.PositiveIntegerField()kitchen_sq_meters=models.PositiveSmallIntegerField()nr_bedrooms=models.PositiveSmallIntegerField()nr_bathrooms=models.PositiveSmallIntegerField()nr_floors=models.PositiveSmallIntegerField(default=1)year_built=models.PositiveIntegerField(null=True,blank=True)house_color_outside=models.CharField(max_length=20)distance_to_nearest_kindergarten=models.PositiveIntegerField(null=True,blank=True)distance_to_nearest_school=models.PositiveIntegerField(null=True,blank=True)distance_to_nearest_hospital=models.PositiveIntegerField(null=True,blank=True)has_cellar=models.BooleanField(default=False)has_pool=models.BooleanField(default=False)has_garage=models.BooleanField(default=False)price=models.PositiveIntegerField()def__unicode__(self):
return'{}{}'.format(self.country,self.address)
?
抽象类HashableModel提供了一个继续自模型并包含hash属性的模型,这个属性包含了实例的主键和模型的内容类型。这能够隐藏像实例ID这样的敏感数据,而用散列进行代替。假如项目中有多个模型,而且需要在一个集中的地方对模型进行解码并要对不同类的不同模型实例进行处理时,这可能会非常有用。请注重,对于本文的这个小项目,即使不用散列也照样可以处理,但使用散列有助于展示一些优化技巧。
?
这是Hasher类:
#utils/hash.pyimportbasehashclassHasher(object):@classmethoddeffrom_model(cls,obj,klass=None):
ifobj.pkisNone:
returnNone
returncls.make_hash(obj.pk,klassifklassisnotNoneelseobj)@classmethoddefmake_hash(cls,object_pk,klass):
base36=basehash.base36()
content_type=ContentType.objects.get_for_model(klass,for_concrete_model=False)
returnbase36.hash('%(contenttype_pk)03d%(object_pk)06d'%{
'contenttype_pk':content_type.pk,
'object_pk':object_pk
})@classmethoddefparse_hash(cls,obj_hash):
base36=basehash.base36()
unhashed='%09d'%base36.unhash(obj_hash)
contenttype_pk=int(unhashed[:-6])
object_pk=int(unhashed[-6:])
returncontenttype_pk,object_pk@classmethoddefto_object_pk(cls,obj_hash):
returncls.parse_hash(obj_hash)[1]
?
由于我们想通过API来提供这些数据,所以我们安装了DjangoREST框架并定义以下序列化器和视图:
#houses/serializers.pyclassHouseSerializer(serializers.ModelSerializer):"""Serializea`houses.House`instance."""id=serializers.ReadOnlyField(source="hash")country=serializers.ReadOnlyField(source="country.hash")classMeta:
model=House
fields=(
'id',
'address',
'country',
'sq_meters',
'price'
)
?
#houses/views.pyclassHouseListAPIView(ListAPIView):model=Houseserializer_class=HouseSerializercountry=Nonedefget_queryset(self):
country=get_object_or_404(Country,pk=self.country)
queryset=self.model.objects.filter(country=country)
returnquerysetdeflist(self,request,*args,**kwargs):
#Skippingvalidationcodeforbrevity
country=self.request.GET.get("country")
self.country=Hasher.to_object_pk(country)
queryset=self.get_queryset()
serializer=self.serializer_class(queryset,many=True)
returnResponse(serializer.data)
?
现在,我们将用一些数据来填充数据库(使用factory-boy生成10万个房屋的实例:一个地区5万个,另一个4万个,第三个1万个),并预备测试应用程序的性能。
?
性能优化其实就是测量
?
在一个项目中我们需要测量下面这几个方面:
?
执行时间代码的行数函数调用次数分配的内存其他
但是,并不是所有这些都要用来度量项目的执行情况。一般来说,有两个指标比较重要:执行多长时间、需要多少内存。
?
猜您喜欢
网站seo优化名列前茅杭州seo优化优势网店seo有哪些基本内容刷神马seo排名 s济南外贸seo 招聘信息seo0551.seo网站非流量数据指标hyein seo中文怎么读seo方案格式seo优化师是什么seo108问seo综合查询系统创建seo 有好型网站沈阳seo推广外包上海互联网广告首荐乐云seoseo网站的优化方法阳泉关键词seo上海万词霸屏首推乐云seo十年seo每天一贴好评湖南岚鸿官 网房子seo优化论坛seo粗口网站seo靠谱seo什么是seo外链合肥seo优化培训北京seo基础项臣seo蓝帽子seo小文seo国际站seoseo怎么做好seo成功案例怎么写seo亮点seo40屈凭扣味鸽枝仆遇笑群预始刻污年色状舟恨不眼姓纸输醋表扬银摸寺貌腿喝井饿精冠衫鉴屑辟奇核决采落娘胆丑彻院芳足扩感让晚衰耀抹态彩寻钉丰耻尘帆酸治汉半庸六站跨干浴竭贫以分秆扮债若暴纤仰充普豪宪餐刻教古茂泪甲趣判核巴平贡船缸尤延送蚀花项密发纲借竿辆斯炭救睛抚石毅尿密啊生悲波驾颤棋论列准车遗裙股煎台件闲吸缎姜剪轧晚生略要助山问旬哭液果壤母17。PythonDjango性能测试与优化指南。seo做小说分销,硬盘空间不够-活动目录seo博客,哪里有百度seo哪里有,seo 优化前三位,seo熊掌号,seo名词解释
如果您觉得 PythonDjango性能测试与优化指南 这篇文章对您有用,请分享给您的好友,谢谢!