호출이 비쌀 때 파이썬에서 단일 책임 원칙 (SRP)을 통해 작업


12

몇 가지 기본 사항 :

  • 파이썬 메소드 호출은 해석되는 본질 때문에 "비싸다" . 이론적으로 코드가 충분히 단순하다면 파이썬 코드를 분해하면 가독성과 재사용 외에도 부정적인 영향을 미칩니다 ( 이는 개발자에게는 큰 이익이 될 수 있습니다 ).
  • 단일 책임 원칙 (SRP)은 코드를 읽기 쉽게 유지하고 테스트 및 유지 관리가 더 쉽습니다.
  • 이 프로젝트에는 읽을 수있는 코드, 테스트 시간 성능을 원하는 특별한 종류의 배경이 있습니다.

예를 들어, 여러 메소드 (x4)를 호출하는 이와 같은 코드는 다음 중 하나 인 것보다 느립니다.

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()

이것과 비교하여 :

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])

이와 같은 것을 병렬화하면 성능이 저하되는 것은 상당히 객관적입니다. 그것은 단지 예일뿐입니다. 내 프로젝트에는 수학과 같은 몇 가지 미니 루틴이 있습니다. 작업하기가 훨씬 쉽지만 프로파일 러는 싫어합니다.


고유 한 구현이 직접 영향을 미치기 때문에 Python의 성능을 저하시키지 않으면 서 SRP를 어떻게 그리고 어디에서 수용합니까?

릴리스를 위해 인라인을 배치하는 일종의 전처리 기와 같은 해결 방법이 있습니까?

아니면 파이썬이 코드 분석을 완전히 처리하는 데 어려움이 있습니까?



19
가치가있는 것에 대해 두 코드 예제 는 책임의 수가 다르지 않습니다. SRP는 방법 계산 연습이 아닙니다.
Robert Harvey

2
@RobertHarvey 당신이 옳습니다, 좋지 않은 예를 드려 죄송합니다. 시간이 있으면 더 좋은 예를 편집하겠습니다. 어느 쪽이든, 가독성과 유지력이 떨어지고 결국 클래스와 그 메소드를 줄이면 SRP가 코드베이스 내에서 무너집니다.
lucasgcb

4
참고 함수 호출은 어떤 언어로 비싼 AOT 컴파일러는 인라인의 고급 스러움이 있지만,
Eevee

6
PyPy와 같은 JITted Python 구현을 사용하십시오. 대부분이 문제를 해결해야합니다.
Bakuriu

답변:


17

파이썬은 단순히 코드 분석을 잘 처리하지 못합니까?

불행히도 예, 파이썬은 느리고 함수를 인라인하고 코드를 추악하게 만들어 성능을 크게 향상시키는 사람들에 대한 많은 일화가 있습니다.

Cython은 해결 방법이 있습니다. Cython은 컴파일 된 버전의 Python이며 훨씬 빠릅니다.

-편집 난 그냥 의견과 다른 답변 중 일부를 해결하고 싶었습니다. 그들의 추력은 아마도 파이썬에 국한되지는 않습니다. 그러나 더 일반적인 최적화.

  1. 문제가 생길 때까지 최적화하지 말고 병목 현상을 찾으십시오.

    일반적으로 좋은 조언. 그러나 '정상적인'코드는 일반적으로 성능이 우수하다고 가정합니다. 항상 그런 것은 아닙니다. 개별 언어와 프레임 워크에는 각각 고유 한 특성이 있습니다. 이 경우 함수가 호출됩니다.

  2. 몇 밀리 초 밖에 안 걸리고 다른 것들은 느려질 것입니다

    강력한 데스크톱 컴퓨터에서 코드를 실행하는 경우 단일 사용자 코드가 몇 초 안에 실행되는 한 신경 쓰지 않아도됩니다.

    그러나 비즈니스 코드는 여러 사용자에 대해 실행되는 경향이 있으며로드를 지원하려면 둘 이상의 시스템이 필요합니다. 코드가 두 배 빠른 속도로 실행되면 사용자 수의 두 배 또는 기계 수의 절반을 가질 수 있습니다.

    머신과 데이터 센터를 소유하고 있다면 일반적으로 CPU 성능에 엄청난 오버 헤드가 발생합니다. 코드가 약간 느리게 실행된다면 적어도 두 번째 머신을 구입해야 할 때까지 코드를 흡수 할 수 있습니다.

    오늘날 필요한 컴퓨팅 성능 만 사용하고 더 이상 더 이상 사용하지 않는 오늘날의 클라우드 컴퓨팅에서는 비 성능 코드에 대한 직접 비용이 있습니다.

    성능을 향상 시키면 클라우드 기반 비즈니스의 주요 비용을 크게 줄일 수 있으며 성능은 실제로 전면 및 중앙에 있어야합니다.


1
Robert의 답변은 이러한 종류의 최적화를 수행하는 데 대한 잠재적 오해에 대한 몇 가지 근거를 다루는 데 도움이되지만 ( 이 질문에 적합 함 ) Python 컨텍스트와 조금 더 직접적으로 상황에 대한 답변이라고 생각합니다.
lucasgcb

2
다소 짧은 죄송합니다. 더 쓸 시간이 없습니다. 그러나 나는 Robert가 이것에 잘못되었다고 생각합니다. 파이썬에 가장 좋은 조언은 프로파일 것으로 보인다 으로 당신 코드입니다. 그나마 당신은 문제가 발견하면이 확대됨 만 최적화 될 것입니다 가정
이완

2
@ Ewan : 내 조언을 따르기 위해 전체 프로그램을 먼저 작성할 필요는 없습니다. 적절한 프로파일 링을 얻기에 방법 하나 또는 둘 이상이 충분합니다.
Robert Harvey

1
당신은 또한 pypy를 시도 할 수 있습니다. 그것은 JITted python입니다
Eevee

2
@Ewan 함수 호출의 성능 오버 헤드에 대해 정말로 걱정한다면 무엇을 하든지 파이썬에는 적합하지 않을 것입니다. 그러나 나는 실제로 많은 예를 생각할 수 없습니다. 대부분의 비즈니스 코드는 IO로 제한되며 CPU 사용량은 일반적으로 네이티브 라이브러리 (numpy, tensorflow 등)를 호출하여 처리됩니다.
Voo

50

많은 잠재적 인 성능 문제는 실제로 실제로 문제가되지 않습니다. 제기 한 문제는 그 중 하나 일 수 있습니다. 즉, 실제 문제가 조기 최적화 라는 증거없이 이러한 문제에 대해 걱정할 필요가 있습니다.

웹 서비스의 프런트 엔드를 작성하는 경우 네트워크를 통한 데이터 전송 비용이 메서드 호출에 걸리는 시간을 훨씬 초과하기 때문에 함수 호출의 성능에 큰 영향을 미치지 않습니다.

비디오 화면을 초당 60 회 새로 고치는 타이트한 루프를 작성하는 경우 중요 할 수 있습니다. 그러나 그 시점에서 파이썬을 사용하여 파이썬을 사용하려고하면 더 큰 문제가 있다고 주장합니다. 파이썬이 적합하지 않은 작업 일 것입니다.

언제나 그렇듯이 측정 하는 방법입니다. 코드에서 성능 프로파일 러 또는 일부 타이머를 실행하십시오. 실제로 실제 문제인지 확인하십시오.


단일 책임 원칙은 법이나 의무가 아닙니다. 지침 또는 원칙입니다. 소프트웨어 디자인은 항상 트레이드 오프에 관한 것입니다. 절대는 없습니다. 가독성 및 / 또는 유지 관리 속도를 절충하는 것은 드문 일이 아니므로 성능 제단에서 SRP를 희생해야 할 수도 있습니다. 그러나 성능 문제가 있다는 것을 알지 못하면 그 절충을하지 마십시오 .


3
클라우드 컴퓨팅을 발명하기 전까지는 이것이 사실이라고 생각합니다. 이제 두 기능 중 하나는 다른 것보다 4 배나 효과적입니다.
Ewan

2
@Ewan은 관심을 가질만큼 충분히 중요한 것으로 측정 될 때까지 4 번 문제가되지 않을 수 있습니다. Foo에 1ms가 걸리고 Bar에 4ms가 걸리면 좋지 않습니다. 네트워크를 통해 데이터를 전송하는 데 200ms가 걸립니다. 그 시점에서 바가 느리다는 것은별로 중요하지 않습니다. (X 배가 느리다는 점을 보여주는 한 가지 가능한 예는 눈에 띄거나 충격적인 차이를 만들지 않으며 반드시
초현실적 인

8
@Ewan 법안을 줄이면 월 15 달러를 절약 할 수 있지만 계약자를 수정하고 테스트하는 데 시간당 125 달러의 시간이 4 시간이 걸린다면, 비즈니스 시간을 할 가치가없는 것 (또는 적어도 옳지 않은 것은 아님)을 쉽게 정당화 할 수 있습니다 이제 시장 출시 시간이 중요한 경우 등). 항상 상충 관계가 있습니다. 한 상황에서 의미가있는 것은 다른 상황에서는 그렇지 않을 수도 있습니다.
Becuzz

3
귀하의 AWS 청구서가 실제로 매우 낮습니다
Ewan

6
@Ewan AWS는 어쨌든 배치별로 천장으로 반올림합니다 (표준은 100ms). 즉, 이러한 종류의 최적화는 다음 청크로 넘어가는 것을 일관되게 피하지 않으면 모든 것을 절약합니다.
Delioth

2

첫째, 몇 가지 설명 : 파이썬은 언어입니다. 파이썬 언어로 작성된 코드를 실행할 수있는 여러 가지 인터프리터가 있습니다. CPython (참조 구현)은 일반적으로 누군가가 "Python"에 대해 구현하는 것처럼 말할 때 참조되는 것이지만 구현마다 크게 다를 수 있으므로 성능 특성에 대해 이야기 할 때 정확해야합니다.

고유 한 구현이 직접 영향을 미치기 때문에 Python의 성능을 저하시키지 않으면 서 SRP를 어떻게 그리고 어디에서 수용합니까?

사례 1) 순수 Python 코드 (<= Python Language version 3.5, 3.6에는 "베타 수준 지원")가 있으며 순수 Python 모듈에만 의존하는 경우 SRP를 모든 곳에서 수용하고 PyPy를 사용하여 실행할 수 있습니다. PyPy ( https://morepypy.blogspot.com/2019/03/pypy-v71-released-now-uses-utf-8.html )는 JIT (Just In Time Compiler) 기능이 있으며 함수를 제거 할 수있는 Python 인터프리터입니다. 실행 된 코드를 추적하여 (예 : 몇 초 IIRC) "웜업"하기에 충분한 시간이있는 한 오버 헤드를 호출하십시오. **

CPython 인터프리터 사용으로 제한되는 경우 느린 함수를 C로 작성된 확장으로 추출 할 수 있으며, 사전 컴파일되어 인터프리터 오버 헤드가 발생하지 않습니다. SRP를 어디에서나 사용할 수는 있지만 코드는 Python과 C로 나뉩니다. SRP를 선택적으로 포기하지만 Python 코드 만 고수하는 것보다 유지 관리가 더 좋든 나쁘 든 팀에 따라 다르지만 성능에 중요한 부분이 있다면 CPython이 해석 한 가장 최적화 된 순수 Python 코드보다 훨씬 빠릅니다. 많은 파이썬에서 가장 빠른 수학적 라이브러리가이 방법 (numpy 및 scipy IIRC)을 사용합니다. 사례 2에 대한 좋은 비법은 ...

사례 2) C 확장을 사용하는 Python 코드가 있거나 C 확장을 사용하는 라이브러리에 의존하는 경우 PyPy는 작성 방법에 따라 유용하거나 유용하지 않을 수 있습니다. 자세한 내용은 http://doc.pypy.org/en/latest/extending.html 을 참조 하십시오 . 그러나 요약에 따르면 CFFI는 오버 헤드가 최소화되고 CType은 느리지 만 (PyPy와 함께 사용하면 CPython보다 느릴 수 있습니다)

Cython ( https://cython.org/ )은 내가 경험하지 않은 또 다른 옵션입니다. 나는 완전성을 위해 그것을 언급하여 내 대답은 "독립적"일 수는 있지만 전문 지식을 주장하지는 않습니다. 제한된 사용으로 인해 PyPy로 "무료로 얻을 수있는"동일한 속도 향상을 위해 더 열심히 노력해야한다고 생각했으며 PyPy보다 더 나은 것이 필요하면 내 C 확장을 작성하는 것이 쉬웠습니다 ( 코드를 다른 곳에서 재사용하거나 라이브러리의 일부를 추출하면 이점이 있습니다. 모든 코드는 여전히 모든 Python 인터프리터에서 실행될 수 있으며 Cython에서 실행할 필요는 없습니다).

PyPy 용으로 작성된 모든 코드는 CPython에서도 실행될 수있는 반면 Cython에 "고정 된"것이 두렵습니다.

** 프로덕션 PyPy에 대한 추가 참고 사항

큰 코드베이스에서 PyPy에 "잠금"시키는 실질적인 효과를 갖는 선택을하는 데 매우주의하십시오. 일부 (매우 인기 있고 유용한) 타사 라이브러리는 앞에서 언급 한 이유로 훌륭하게 재생되지 않기 때문에 나중에 해당 라이브러리 중 하나가 필요하다는 것을 알게되면 매우 어려운 결정을 내릴 수 있습니다. 필자의 경험은 주로 PyPy를 사용하여 프로덕션 환경에 무시할 수없는 복잡성을 추가하는 회사 환경에서 성능에 민감한 일부 (전부는 아님) 마이크로 서비스의 속도를 높이는 것입니다. 3.5 어쨌든 달리기).

PyPy와 CPython을 모두 정기적으로 사용하면 언어 사양 자체에 의한 보증에만 의존하고 언제든지 변경 될 수있는 구현 세부 사항이 아닌 코드를 작성해야한다는 것을 알았습니다. 그러한 세부 사항에 대한 생각이 추가 부담이라고 생각할 수도 있지만, 나는 전문적인 개발에서 가치가 있다는 것을 알았으며, 파이썬 생태계 전체에서 이것이 "건강"하다고 생각합니다.


네! 필자는 원칙을 포기하고 와일드 코드를 작성하는 대신이 사례의 C 확장에 중점을두고 있었지만 다른 답변은 참조 통역사와 교환하지 않으면 속도가 느릴 것이라는 인상을주었습니다. 당신의 관점에서 합리적인 접근 방법이 있습니까?
lucasgcb

1
사례 1 (2 번째 단락)을 사용하면 함수 자체가 준수 되더라도 함수를 호출 하는 오버 헤드가 동일하지 않습니까?
Ewan

CPython은 일반적으로 진지하게 받아 들여지는 유일한 통역사입니다. PyPy는 흥미롭지 만 확실히 널리 채택되지는 않습니다. 또한 동작 CPython 과 다르며 scipy와 같은 일부 중요한 패키지에서는 작동하지 않습니다. 제정신의 개발자가 프로덕션에 PyPy를 추천하는 사람은 거의 없습니다. 따라서 언어와 구현의 구별은 실제로 중요하지 않습니다.
jpmc26

그래도 머리에 못을 박았다고 생각합니다. 더 나은 통역사 나 컴파일러를 가질 수 없었습니다. 파이썬을 언어로 내재하지는 않습니다. 당신은 실제 현실에 갇혀 있습니다
Ewan

@ jpmc26 프로덕션 환경에서 PyPy를 사용했으며 다른 숙련 된 개발자에게이를 고려하는 것이 좋습니다. 경량 레스트 API (예 : falconframework.org) 를 사용하는 마이크로 서비스에 적합 합니다. 개발자가 언어를 보장하지 않는 구현 세부 사항에 의존하기 때문에 동작이 다르기 때문에 PyPy를 사용하지 않는 것은 아닙니다. 코드를 다시 작성해야하는 이유입니다. CPython이 구현을 변경하면 (언어 스펙을 준수하는 한 자유롭게 수행 할 수 있음) 동일한 코드가 어쨌든 중단 될 수 있습니다.
Steven Jackson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.