시스템 작업 경험이있는 사람들에게 Visual Studio의 규모를 물어보고 싶습니다. 속도를 늦추는 것은 무엇입니까? 인간의 이해 능력 내에서 코드베이스를 유지하는 데 필요한 추상화 계층의 계층입니까? 실행해야하는 코드의 양입니까? 클럭 사이클 / 메모리 사용 부서에서 (마음이 큰) 비용으로 프로그래머 시간 절약 방식에 대한 현대적인 경향입니까?
나는 당신이 그중 많은 것을 추측했다고 생각하지만 상당히 큰 코드베이스에서 작업 한 가장 큰 요인으로 생각하고 싶습니다 (Visual Studio만큼 큰지 확실하지 않습니다-수백만 줄의 코드에 있음) 약 10 년 동안 카테고리 및 약 1,000 개의 플러그인)을 관찰하고 현상을 관찰합니다.
API 나 언어 기능 또는 이와 유사한 것에 빠지지 않기 때문에 논란의 여지가 적습니다. 그것들은 "지출"보다는 토론을 낳을 수있는 "비용"과 관련이 있으며, "지출"에 집중하고 싶습니다.
느슨한 조정 및 레거시
내가 관찰 한 것은 느슨한 조정과 긴 유산은 많은 축적 된 폐기물을 초래하는 경향이 있다는 것입니다.
예를 들어,이 코드베이스에서 약 100 개의 가속 구조를 발견했는데, 그중 다수는 중복입니다.
우리는 하나의 물리 엔진을 가속화하기위한 KD 트리를 원했고, 다른 하나는 종종 오래된 것과 병렬로 실행되는 새로운 물리 엔진을 위해, 또 다른 메시 알고리즘을위한 수십 개의 옥트리 구현, 렌더링을위한 또 다른 KD 트리를 가지고있었습니다. , 피킹 등 등등. 이들은 모두 검색을 가속화하는 데 사용되는 크고 부피가 큰 트리 구조입니다. 각각의 개인은 평균 크기의 입력을 위해 수백 메가 바이트에서 기가 바이트의 메모리를 사용할 수 있습니다. 항상 인스턴스화되어 사용되는 것은 아니지만 주어진 시간에 4 개 또는 5 개가 동시에 메모리에있을 수 있습니다.
이제 이들 모두는 동일한 데이터를 저장하여 검색 속도를 높였습니다. 모든 필드를 한 번에 20 개의 서로 다른 중복 맵 / 사전 / B + 트리에 저장하고 동일한 키로 동일하게 구성하고 항상 모든 필드를 검색하는 유사 오래된 데이터베이스와 같이 상상할 수 있습니다. 지금 우리는 20 배의 메모리와 처리를하고 있습니다.
또한 이중화로 인해 유지 보수 가격표를 사용하여 이들 중 하나를 최적화 할 시간이 거의 없으며, 그렇게해도 이상적인 효과의 5 % 만 가질 수 있습니다.
이 현상의 원인은 무엇입니까? 느슨한 조정은 내가 본 가장 큰 원인이었습니다. 많은 팀원이 종종 고립 된 생태계에서 일하면서 제 3 자 데이터 구조를 개발하거나 사용하지만 다른 팀 구성원이 동일한 우려 사항을 똑같이 명백하게 복제하더라도 동일한 구조를 사용하지는 않습니다.
이 현상이 지속되는 원인은 무엇입니까? 레거시와 호환성은 내가 본 가장 큰 원인이었습니다. 우리는 이미 이러한 데이터 구조를 구현하는 비용을 지불했으며 많은 양의 코드가 이러한 솔루션에 의존하기 때문에 데이터 구조를 더 적은 수의 데이터 구조로 통합하는 것은 너무 위험했습니다. 이러한 많은 데이터 구조는 개념 상 중복성이 높았지만 인터페이스 디자인에서 항상 동일한 위치에있는 것은 아닙니다. 따라서 메모리와 처리 시간을 소비하게하는 것과는 대조적으로 그것들을 교체하는 것은 크고 위험한 변화였습니다.
메모리 효율
일반적으로 메모리 사용 및 속도는 최소한 벌크 레벨에서 관련되는 경향이 있습니다. 메모리가 많이 소모되는 방식으로 느린 소프트웨어를 발견 할 수 있습니다. 그것은 아니다 항상 어떤 중요한 것은 모든 시간을 액세스하는 것을 메모리 "핫"메모리 (이후, 경기 둔화에 더 많은 메모리 리드 진정한 - 프로그램이 메모리의 적재량을 사용하지만 그것의 1메가바이트 모두를 사용중인 경우 시간이 지나면 속도가 그렇게 큰 문제는 아닙니다).
따라서 많은 시간 동안 메모리 사용량을 기반으로 잠재적 호그를 발견 할 수 있습니다. 응용 프로그램을 시작할 때 수백에서 수백 메가 바이트의 메모리가 필요한 경우에는 그다지 효율적이지 않을 것입니다. 요즘 기가 바이트의 DRAM을 사용하면 수십 메가 바이트가 작게 보일 수 있지만 가장 크고 느린 CPU 캐시는 여전히 메가 바이트 범위에 있으며 가장 빠른 속도는 여전히 킬로바이트 범위에 있습니다. 결과적으로, 시작하고 아무것도하지 않고 20MB를 사용하는 프로그램은 실제로 하드웨어 CPU 캐시 관점에서 실제로 "많은"메모리를 사용하고 있습니다. 특히 해당 메모리의 모든 20MB가 반복적으로 액세스 될 경우 프로그램이 실행되는 동안 자주.
해결책
나에게 해결책은 제품을 만들기 위해보다 조율 된 소규모 팀을 찾는 것인데, "지출"을 추적하고 같은 품목을 계속해서 "구매"하는 것을 피할 수있는 팀을 찾는 것이다.
비용
나는 내가 관찰 한 "지출"현상과 함께 좀 더 논란이 많은 "비용"측면에 대해 조금만 언급 할 것이다. 언어에 객체에 대한 불가피한 가격표 (예 : 런타임 리플렉션을 제공하고 일련의 객체에 대해 연속적인 할당을 강제 할 수없는 가격표)가있는 경우 해당 가격표는 단일 Pixel
또는 Boolean
.
그러나 그 정도의 세분화 된 수준으로 그 비용을 지불 하는 무거운로드 (예 : 수십만에서 수백만 Pixel
또는 Boolean
인스턴스 처리)를 처리하는 프로그램에 대한 많은 소스 코드가 있습니다 .
객체 지향 프로그래밍은 그것을 악화시킬 수 있습니다. 그러나 그것은 "오브젝트"자체의 비용이 아니거나 심지어 OOP의 결함이 아니라, 단순히 그러한 비용이 수백만에 의해 인스턴스화 될 조그마한 요소의 세분화 된 수준으로 지불되고 있다는 것입니다.
이것이 제가 관찰하고있는 다른 "비용"과 "지출"현상입니다. 비용은 페니이지만, 대량 구매를 위해 제조업체와 협상하는 대신 백만 캔의 음료수를 개별적으로 구매하는 경우 페니가 추가됩니다.
나에게 해결책은 "대량"구매입니다. 소다 캔에 해당하는 유사체에 대해이 비용이 개별적으로 백만 배 이상 지불되지 않는 한, 각각에 대해 가격이 책정되어 있습니다.
조기 최적화
"초기 최적화"로 인해 실제 제작 프로그램이 더 빨리 진행되는 경우는 드물기 때문에 여기에 사용 된 단어 Knuth를 좋아하지 않았습니다. 일부는 Knuth가 "소프트웨어에 미치는 실제 영향을 알기 위해 적절한 지식 / 경험없이 최적화하는 것"과 같은 의미 일 때 "조기 최적화"로 해석합니다. 유지 관리 성이 저하되면 중요한 경로를 실제로 최적화 할 시간이 거의 없기 때문에 진정한 조기 최적화의 실질적인 효과로 인해 소프트웨어 속도가 느려지 는 경우가 많습니다 .
이것이 내가 관찰 한 마지막 현상인데, 개발자가 소다 캔 1 개를 구매할 때 동전을 구하기 위해, 다시는 집을 사거나 더 나쁜 집을 구입하지 않아도 페니를 꼬집어 다니는 시간을 낭비하고있었습니다. 다른 곳에서 낭비하는 수십억 달러가 있었을 때 컴파일러 또는 하드웨어 아키텍처를 이해하지 못했습니다.
시간이 매우 한정되어 있으므로 상황에 맞는 적절한 정보를 얻지 않고 절대 값을 최적화하려고하면 실제로 중요한 장소를 최적화 할 수있는 기회를 종종 빼앗기 게되므로 실질적인 효과 측면에서 "초기 최적화를하면 소프트웨어 속도가 훨씬 느려집니다. "
문제는 위에서 객체에 대해 작성한 것을 취하고 객체 지향 프로그래밍 또는 그러한 종류의 미친 것을 금지하는 코딩 표준을 설정하려고하는 개발자 유형이 있다는 것입니다. 효과적인 최적화는 효과적인 우선 순위이며, 유지 관리 문제가 발생하면 절대 가치가 없습니다.