Aramalar pahalı olduğunda Python'daki tek sorumluluk ilkesi (SRP) ile çalışmak


12

Bazı temel noktalar:

  • Yorumlanan doğası nedeniyle Python yöntem çağrıları "pahalıdır" . Teoride, kodunuz yeterince basitse, Python kodunun parçalanması okunabilirlik ve yeniden kullanımın yanı sıra olumsuz bir etkiye sahiptir ( bu, geliştiriciler için büyük bir kazançtır, kullanıcılar için çok fazla değildir ).
  • Tek sorumluluk ilkesi (SRP) kodu okunabilir tutar, test edilmesi ve bakımı daha kolaydır.
  • Proje, okunabilir kod, testler ve zaman performansı istediğimiz özel bir arka plana sahiptir .

Örneğin, birkaç yöntemi (x4) çağıran böyle bir kod, aşağıdakilerden daha yavaştır;

from operator import add

class Vector:
    def __init__(self,list_of_3):
        self.coordinates = list_of_3

    def move(self,movement):
        self.coordinates = list( map(add, self.coordinates, movement))
        return self.coordinates

    def revert(self):
        self.coordinates = self.coordinates[::-1]
        return self.coordinates

    def get_coordinates(self):
        return self.coordinates

## Operation with one vector
vec3 = Vector([1,2,3])
vec3.move([1,1,1])
vec3.revert()
vec3.get_coordinates()

Buna kıyasla:

from operator import add

def move_and_revert_and_return(vector,movement):
    return list( map(add, vector, movement) )[::-1]

move_and_revert_and_return([1,2,3],[1,1,1])

Eğer böyle bir şeyi paralel hale getireceksem, performansı kaybetmem oldukça objektiftir. Zihin sadece bir örnek; Projemde matematik gibi birkaç mini rutin var - Çalışmak çok daha kolay olsa da, profilcilerimiz bunu sevmiyor.


İçsel uygulaması doğrudan etkilediğinden, SRP'yi Python'daki performanstan ödün vermeden nasıl ve nerede kucaklayabiliriz?

İşleri serbest bırakmak için sıraya koyan bir tür ön işlemci gibi geçici çözümler var mı?

Yoksa Python kod dökümünü tamamen ele almada yetersiz mi?



19
Değeri ne olursa olsun, iki kod örneğiniz sorumlulukların sayısından farklı değildir. SRP bir yöntem sayma egzersizi değildir.
Robert Harvey

2
@RobertHarvey Haklısın, kötü örnek için özür dilerim ve zamanım olduğunda daha iyi bir tane düzenleyeceğim. Her iki durumda da, okunabilirlik ve bakım kolaylığı zarar görür ve sonunda sınıflar ve yöntemlerini kısarken SRP kod tabanı içinde bozulur.
lucasgcb

4
fonksiyon çağrılarının herhangi bir dilde pahalı olduğunu unutmayın , ancak AOT derleyicileri satır içi lüksüne sahiptir
Eevee

6
PyPy gibi bir JITted python uygulaması kullanın. Çoğunlukla bu sorunu çözmeli.
Bakuriu

Yanıtlar:


17

Python kod dökümü tamamen ele almakta yetersiz mi?

Ne yazık ki evet, Python yavaş ve fonksiyonları satır içine alarak ve kodlarını çirkin hale getirerek performansı önemli ölçüde artıran insanlar hakkında birçok fıkra vardır.

Etrafında bir çalışma var, Cython, Python'un derlenmiş bir versiyonu ve çok daha hızlı.

- Düzenleme Sadece bazı yorumları ve diğer cevapları ele almak istedim. Rağmen onları itme belki python özgü değildir. ancak daha genel optimizasyon.

  1. Bir sorununuz olana kadar optimizasyon yapmayın ve ardından darboğaz arayın

    Genellikle iyi tavsiye. Ancak varsayım 'normal' kodun genellikle yerine getirildiğidir. Bu her zaman böyle değildir. Bireysel diller ve çerçevelerin her birinin kendi kendine özgü özellikleri vardır. Bu durumda işlev çağırır.

  2. Sadece birkaç milisaniye, diğer şeyler daha yavaş olacak

    Kodunuzu güçlü bir masaüstü bilgisayarda çalıştırıyorsanız, tek kullanıcı kodunuz birkaç saniye içinde çalıştığı sürece büyük olasılıkla umursamazsınız.

    Ancak işletme kodu birden çok kullanıcı için çalışır ve yükü desteklemek için birden fazla makine gerektirir. Kodunuz iki kat daha hızlı çalışırsa, iki kat kullanıcı veya makine sayısının yarısı olabilir.

    Makinelerinize ve veri merkezinize sahipseniz, genellikle CPU gücünde büyük bir ek yüke sahipsiniz. Kodunuz biraz yavaş çalışıyorsa, en azından ikinci bir makine satın almanız gerekene kadar emebilirsiniz.

    Yalnızca tam olarak ihtiyaç duyduğunuz hesaplama gücünü kullandığınız ve artık kullanmamanız gereken bulut bilişim bu günlerde, performanssız kod için doğrudan bir maliyet vardır.

    Performansı artırmak, bulut tabanlı bir işletme için ana masrafı büyük ölçüde azaltabilir ve performans gerçekten ön ve merkez olmalıdır.


1
Robert'in Cevabı, bu tür bir optimizasyon yapmanın arkasındaki olası yanlış anlamalar için bazı temelleri kapsamaya yardımcı olsa da ( bu soruya uyuyor ), bunun duruma biraz daha doğrudan ve Python bağlamıyla uyumlu olduğunu düşünüyorum.
lucasgcb

2
üzgünüm biraz kısa. Daha fazla yazacak vaktim yok. Ama bence Robert bu konuda yanlış. Piton ile en iyi tavsiye profile gibi görünüyor olarak size kod. Dont varsayalım performans ve sadece bir sorun bulursanız optimize
Ewan

2
@Ewan: Tavsiyemi takip etmek için önce tüm programı yazmak zorunda değilsiniz. Bir veya iki yöntem yeterli profil elde etmek için fazlasıyla yeterlidir.
Robert Harvey

1
Ayrıca JITted bir python olan pypy'yi de deneyebilirsiniz
Eevee

2
@Ewan İşlev çağrılarının performans yükü konusunda gerçekten endişe duyuyorsanız, yaptığınız her şey muhtemelen python için uygun değildir. Ama o zaman burada pek çok örnek düşünemiyorum. İş kodunun büyük çoğunluğu IO sınırlıdır ve CPU ağır işleri genellikle yerel kütüphanelere (numpy, tensorflow vb.) Çağrılarak işlenir.
Voo

50

Birçok potansiyel performans endişesi pratikte gerçekten bir sorun değildir. Ortaya koyduğunuz sorun bunlardan biri olabilir. Yerel dilde, gerçek problemlerin erken optimizasyon olduğuna dair kanıt olmadan bu problemler hakkında endişe duyuyoruz .

Bir web hizmeti için kullanıcı arabirimi yazıyorsanız, bir ağ üzerinden veri gönderme maliyeti bir yöntem çağrısı yapmak için gereken süreyi çok aştığından performansınız işlev çağrılarından önemli ölçüde etkilenmeyecektir.

Bir video ekranını saniyede altmış kez yenileyen sıkı bir döngü yazıyorsanız, önemli olabilir. Ama bu noktada, bunu yapmak için Python'u kullanmaya çalışıyorsanız, Python'un muhtemelen uygun olmadığı bir iş olduğunu daha büyük sorunlarınız olduğunu iddia ediyorum.

Her zaman olduğu gibi, bulmanın yolu ölçmektir. Kodunuz üzerinde bir performans profili veya bazı zamanlayıcılar çalıştırın. Uygulamada gerçek bir sorun olup olmadığına bakın.


Tek Sorumluluk İlkesi bir yasa veya yetki değildir; bir kılavuz ilkedir. Yazılım tasarımı daima değiş tokuşlarla ilgilidir; mutlak yoktur. Hız için okunabilirlik ve / veya sürdürülebilirlikten ödün vermek alışılmadık bir durum değildir, bu nedenle performans sunaklarından SRP'yi feda etmeniz gerekebilir. Ancak bir performans sorununuz olduğunu bilmiyorsanız bu ödünleşmeyi yapmayın .


3
Bulut bilgi işlemini icat edene kadar bunun doğru olduğunu düşünüyorum. Şimdi iki fonksiyondan biri diğerinden 4 kat daha etkili
Ewan

2
@ Ewan, dikkat etmeniz gereken kadar önemli olduğunu ölçene kadar 4 kez önemli olmayabilir. Foo 1 ms sürüyor ve Bar 4 ms sürüyorsa bu iyi değildir. Veriyi ağ üzerinden iletmenin 200 ms sürdüğünü anlayana kadar. Bu noktada, Bar'ın daha yavaş olması çok önemli değil. (X kez daha yavaş olmanın olası bir örneği, mutlaka süper gerçekçi olması gerekmeyen, fark edilir veya etkili bir fark
yaratmaz

8
@Ewan Eğer tasarının azaltılması size 15 $ / ay tasarruf sağlıyorsa, ancak bunu düzeltmek ve test etmek için 125 $ / saat yüklenici 4 saat sürecekse, bir işletmenin zamanına değmemenin (ya da en azından doğru yapmamaya) kolayca haklı çıkarabilirim. şimdi pazara zaman çok önemli ise, vb.). Her zaman ödünleşmeler vardır. Ve bir durumda mantıklı olan başka bir durumda olmayabilir.
Becuzz

3
AWS faturalarınız gerçekten çok düşük
Ewan

6
@Ewan AWS yine de yığınlarla tavana yuvarlar (standart 100 ms'dir). Bu da, bu tür bir optimizasyonun, sizi sürekli olarak bir sonraki parçaya göndermekten kaçınması durumunda size her şeyi kaydedeceği anlamına gelir.
Delioth

2

İlk olarak, bazı açıklamalar: Python bir dildir. Python dilinde yazılmış kodu çalıştırabilen birkaç farklı tercüman vardır. Referans uygulama (CPython) genellikle birisi bir uygulama gibi "Python" dan bahsettiğinde atıfta bulunulan şeydir, ancak uygulamalar arasında çılgınca farklılık gösterebileceğinden performans özellikleri hakkında konuşurken kesin olmak önemlidir.

İçsel uygulaması doğrudan etkilediğinden, SRP'yi Python'daki performanstan ödün vermeden nasıl ve nerede kucaklayabiliriz?

Durum 1.) Sadece Python modüllerine dayanan saf Python kodunuz (<= Python Language sürüm 3.5, 3.6 "beta seviyesi desteği" vardır), SRP'yi her yerde kucaklayabilir ve çalıştırmak için PyPy kullanabilirsiniz. PyPy ( https://morepypy.blogspot.com/2019/03/pypy-v71-released-now-uses-utf-8.html ) Tam Zamanında Derleyici (JIT) içeren ve işlevi kaldırabilen bir Python yorumlayıcısıdır yürütülen kodu (birkaç saniye IIRC) izleyerek "ısınmak" için yeterli zaman olduğu sürece tepegöz çağırın. **

CPython yorumlayıcısını kullanmakla kısıtlıysanız, yavaş işlevleri C'de yazılmış uzantılara ayıklayabilirsiniz, bunlar önceden derlenecek ve herhangi bir tercüman yükü ile karşılaşmayacaktır. Yine de SRP'yi her yerde kullanabilirsiniz, ancak kodunuzun Python ve C arasında bölünmesi gerekir. Şüphesiz, CPython tarafından yorumlanan en iyileştirilmiş saf Python kodundan bile daha hızlı olacaktır. Python'un en hızlı matematiksel kütüphanelerinin çoğu bu yöntemi kullanır (numpy ve scipy IIRC). Hangi Durum 2 güzel bir segue olduğunu ...

Durum 2.) C uzantıları kullanan (veya C uzantıları kullanan kitaplıklara dayanan ) Python kodunuz varsa, PyPy nasıl yazıldıklarına bağlı olarak yararlı olabilir veya olmayabilir. Ayrıntılar için http://doc.pypy.org/tr/latest/extending.html adresine bakın, ancak özet, CTypes daha yavaşken CFFI'nin minimum ek yüke sahip olmasıdır (PyPy ile kullanmak CPython'dan daha yavaş olabilir)

Cython ( https://cython.org/ ) bu kadar deneyimim olmayan başka bir seçenektir. Tamlık uğruna bundan bahsediyorum, böylece cevabım "kendi başına durabilir", ancak herhangi bir uzmanlık talep etmeyin. Sınırlı kullanımımdan, PyPy ile "ücretsiz" alabileceğim aynı hız iyileştirmelerini elde etmek için daha fazla çalışmak zorunda kaldım ve PyPy'den daha iyi bir şeye ihtiyacım olursa, kendi C uzantımı yazmak kadar kolaydı ( kodu başka bir yerde yeniden kullanırsam veya bir kısmını bir kütüphaneye çıkarırsam, tüm kodlarım hala herhangi bir Python Tercümanı altında çalışabilir ve Cython tarafından çalıştırılması gerekmez).

Pypy için yazılmış herhangi bir kod CPython altında da çalışabilir iken, Cython "kilitli" olmaktan korkuyorum.

** Üretimde PyPy hakkında bazı ekstra notlar

Büyük bir kod tabanında PyPy'ye "sizi kilitlemek" gibi pratik bir etkiye sahip olan seçimleri yaparken çok dikkatli olun. Bazı (çok popüler ve yararlı) üçüncü parti kütüphaneler daha önce belirtilen nedenlerle iyi oynamadıkları için, daha sonra bu kütüphanelerden birine ihtiyacınız olduğunu fark ederseniz çok zor kararlara neden olabilir. Deneyimim öncelikle, üretim ortamımıza ihmal edilebilir bir karmaşıklık eklediği bir şirket ortamında performansa duyarlı bazı (ancak hepsi değil) mikro hizmetlerin hızlandırılması için PyPy'yi kullanmaktır (zaten 2.7 vs gibi farklı ana sürümleri olan birden fazla dil konuşlandırılmıştır. 3.5 zaten çalışıyor).

Hem PyPy hem de CPython kullanmanın düzenli olarak beni her zaman değişikliğe tabi olan uygulama ayrıntılarına değil, yalnızca dil spesifikasyonunun kendisi tarafından yapılan garantilere dayanan bir kod yazmaya zorladığını gördüm. Bu tür ayrıntıların fazladan bir yük olduğunu düşünebilirsiniz, ancak bunu profesyonel gelişimimde değerli buldum ve bence Python ekosistemi için bir bütün olarak "sağlıklı".


Evet! Prensibi terk etmek ve vahşi kod yazmak yerine bu dava için C uzantılarına odaklanmayı düşündüm, diğer cevaplar referans yorumlayıcıdan takas olmadıkça ne kadar yavaş olacağı izlenimi verdi - Temizlemek için, OOP yine de mantıklı bir yaklaşım olabilir mi?
lucasgcb

1
case 1 (2nd para) ile , işlevlerin kendilerine uyulsa bile işlevleri çağırarak aynı şeyi alamazsınız ?
Ewan

CPython genellikle ciddiye alınan tek yorumlayıcıdır. PyPy ilginç , ama kesinlikle herhangi bir yaygın kabul görmüyor. Ayrıca, davranışı CPython'dan farklıdır ve scipy gibi bazı önemli paketlerle çalışmaz. Birkaç aklı başında geliştirici PyPy'yi üretim için tavsiye ederdi. Bu nedenle, dil ve uygulama arasındaki ayrım pratikte önemsizdir.
jpmc26

Bence kafasına çiviyi vurdun. Daha iyi bir tercümana veya bir derleyiciye sahip olmanız için hiçbir neden yok. Bir dil olarak python'a özgü değildir. Pratik gerçeklerle sıkışıp
Ewan

@ jpmc26 Üretimde PyPy kullandım ve bunu diğer deneyimli geliştiricilere kullanmayı düşünmenizi tavsiye ederim. Hafif dinlenme API'ları için falconframework.org kullanan mikro hizmetler için mükemmeldir (bir örnek olarak). Davranış farklıdır, çünkü geliştiriciler dilin garantisi OLMAYAN uygulama ayrıntılarına güvenirler PyPy'yi kullanmamanın bir nedeni değildir. Kodunuzu yeniden yazmak için bir neden. Aynı kod, CPython uygulamasında değişiklikler yaparsa (yine de dil spesifikasyonuna uyduğu sürece ücretsizdir) yine de kırılabilir.
Steven Jackson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.