[performance] 당신이 본 가장 우스운 비관은 무엇입니까? [닫은]

우리는 조기 최적화가 코드를 읽을 수 없거나 유지할 수 없기 때문에 모든 악의 근원이라는 것을 알고 있습니다. 누군가가 “최적화”를 구현하면 더 빠를 것이라고 생각 하기 때문에 비관 화가 더 심해 집니다. 그러나 더 느리고 결국 버그가 많고 유지 관리가 불가능한 등의 결과가 나옵니다. ?



답변

오래된 프로젝트에서 우리는 방대한 Z-8000 경험을 가진 일부 (그렇지 않으면 우수한) 임베디드 시스템 프로그래머를 물려 받았습니다.

우리의 새로운 환경은 32 비트 Sparc Solaris였습니다.

RAM 중 16 비트를 잡는 것이 32 비트를 잡는 것보다 빠르기 때문에 녀석 중 한 명이 가서 모든 정수를 반바지로 변경하여 코드 속도를 높였습니다.

32 비트 시스템에서 32 비트 값을 잡는 것이 16 비트 값을 잡는 것보다 빠르다는 것을 보여주기 위해 데모 프로그램을 작성해야했으며 16 비트 값을 잡으려면 CPU가 32 비트 너비를 가져야한다고 설명했습니다 메모리 액세스 후 16 비트 값에 필요하지 않은 비트를 마스킹 또는 시프트합니다.


답변

“초기 최적화는 모든 악의 근원”이라는 문구가 사용 된 방식이라고 생각합니다. 많은 프로젝트의 경우 프로젝트 후반까지 성능을 고려하지 않는 것이 변명되었습니다.

이 문구는 종종 사람들이 일을 피하기위한 목발입니다. 나는 사람들이 정말로 “Gee, 우리는 그것을 미리 생각하지 않았고 지금 그것을 다룰 시간이 없다”고 말할 때이 문구가 사용 된 것을 본다.

나는 “pesimization”으로 인해 발생한 문제의 예보다 멍청한 성능 문제에 대한 더 많은 “우스꽝스러운”예를 보았습니다.

  • 프로그램 시작 동안 같은 레지스트리 키를 수천 번 (또는 수만) 읽는다.
  • 동일한 DLL을 수백 또는 수천 번로드
  • 불필요하게 파일의 전체 경로를 유지하여 메가 바이트의 메모리 낭비
  • 데이터 구조를 구성하지 않으므로 필요한 것보다 더 많은 메모리를 차지합니다.
  • 파일 이름 또는 경로를 MAX_PATH에 저장하는 모든 문자열 크기 조정
  • 이벤트, 콜백 또는 기타 알림 메커니즘이있는 대상에 대한 무료 폴링

내가 더 나은 진술이라고 생각하는 것은 “측정과 이해없는 최적화는 전혀 최적화가 아니라 무작위 변화”라는 것이다.

우수한 성능 작업은 시간이 많이 걸리며 기능 또는 구성 요소 자체의 개발에 더 많은 시간이 소요됩니다.


답변

데이터베이스는 비관적 인 플레이 랜드입니다.

즐겨 찾기에는 다음이 포함됩니다.

  • 테이블이 너무 커서 날짜 범위, 알파벳 범위 등으로 여러 테이블로 나눕니다.
  • 폐기 된 레코드에 대한 아카이브 테이블을 작성하지만 프로덕션 테이블과 계속 UNION하십시오.
  • (구분 / 고객 / 제품 / 등)에 의해 전체 데이터베이스 복제
  • 열이 너무 커지므로 인덱스에 열을 추가하지 마십시오.
  • 원시 데이터에서 재 계산이 너무 느리므로 많은 요약 테이블을 작성하십시오.
  • 공간을 절약하기 위해 서브 필드로 열을 작성하십시오.
  • 필드를 배열로 비정규 화합니다.

그것은 내 머리 꼭대기에서 벗어났다.


답변

나는 절대적인 규칙이 없다고 생각합니다. 어떤 것들은 가장 잘 최적화되어 있고 어떤 것은 그렇지 않습니다.

예를 들어 위성에서 데이터 패킷을 수신 한 회사에서 근무했습니다. 각 패킷은 많은 비용이 들기 때문에 모든 데이터가 고도로 최적화되었습니다 (즉, 압축). 예를 들어 위도 / 경도는 절대 값 (부동)으로 전송되지 않고 “현재”영역의 “북서쪽”코너에 상대적인 오프셋으로 전송되었습니다. 사용하기 전에 모든 데이터의 압축을 풀어야했습니다. 그러나 이것은 비관적이지 않다고 생각합니다. 통신 비용을 줄이는 것은 지능적인 최적화입니다.

반면 소프트웨어 설계자는 압축을 푼 데이터를 읽을 수있는 XML 문서로 형식화하고 각 열을 해당 열에 저장하는 것과 달리 데이터베이스에 저장해야한다고 결정했습니다. 그들의 아이디어는 “XML은 미래입니다”, “디스크 공간은 싸다”, “프로세서는 싸다”라는 것이므로 아무것도 최적화 할 필요가 없었습니다. 그 결과 16 바이트 패킷이 한 열에 저장된 2kB 문서로 바뀌 었으며 간단한 쿼리조차도 메가 바이트의 XML 문서를 메모리에로드해야했습니다! 초당 50 개가 넘는 패킷을 받았으므로 성능이 얼마나 끔찍한 지 상상할 수 있습니다 (BTW, 회사 파산).

다시 말하지만 절대 규칙은 없습니다. 예, 때로는 너무 일찍 최적화하는 것은 실수입니다. 그러나 때때로 “cpu / disk space / memory is cheap”모토는 모든 악의 근원입니다.


답변

오 주여, 나는 그들 모두를 본 것 같아요. 너무 자주 게으른 사람이 성능 문제의 원인으로 문제를 해결하거나 실제로 성능 문제가 있는지 여부를 조사하기 위해 성능 문제를 해결하려는 노력이 종종 있습니다. 이 중 많은 경우에 특정 기술을 시험 해보고 싶어하는 사람이 반짝이는 새 망치에 맞는 못을 필사적으로 찾고 있는지 궁금합니다.

최근 예는 다음과 같습니다.

데이터 아키텍트는 상당히 크고 복잡한 응용 프로그램에서 키 테이블을 세로로 분할하는 정교한 제안을 제공합니다. 그는 변화에 적응하기 위해 어떤 유형의 개발 노력이 필요한지 알고 싶어합니다. 대화는 다음과 같이 진행되었습니다.

나 : 왜 이걸 고려하고 있니? 해결하려는 문제는 무엇입니까?

그를: 표 X가 너무 넓어서 성능상의 이유로 분할하고 있습니다.

나 : 왜 그렇게 넓다고 생각하니?

컨설턴트 : 컨설턴트는 한 테이블에 너무 많은 열이 있다고 말했다.

나 : 그리고 이것은 성능에 영향을 미치고 있습니까?

사용자 : 그렇습니다. 사용자는 애플리케이션의 XYZ 모듈에서 간헐적 인 속도 저하를보고했습니다.

나 : 테이블 너비가 문제의 원인이라는 것을 어떻게 알 수 있습니까?

그 : 그것은 XYZ 모듈이 사용하는 키 테이블이며, 200 열과 같습니다. 문제가되어야합니다.

Me (설명) : 그러나 XYZ 모듈은 특히 해당 테이블의 대부분의 열을 사용하며 사용자가 해당 테이블에서 표시하려는 데이터를 표시하도록 앱을 구성하기 때문에 사용하는 열을 예측할 수 없습니다. 그것은 시간의 95 %는 우리가 것이다 어쨌든 다시 함께 모든 테이블을 조인 바람 줄 가능성이 상처 성능을.

그 : 컨설턴트는 너무 넓어서 변경해야한다고 말했습니다.

나 : 이 컨설턴트는 누구입니까? 컨설턴트를 고용하거나 개발 팀과 전혀 대화하지 않았습니다.

그분 : 글쎄, 우리는 아직 그들을 고용하지 않았습니다. 이것은 그들이 제안한 제안의 일부이지만, 우리는이 데이터베이스를 재구성 할 필요가 있다고 주장했다.

나 : 어. 데이터베이스 재 설계 서비스를 판매하는 컨설턴트는 데이터베이스 재 설계가 필요하다고 생각합니다.

대화는 이런 식으로 진행되었습니다. 그 후, 문제의 테이블을 다시 살펴보고 이국적인 분할 전략이 필요하지 않은 간단한 정규화로 좁힐 수 있다고 결정했습니다. 물론 성능 문제 (이전에는보고되지 않음)를 조사하고 다음 두 가지 요소로 추적하면 문제가 될 수 있습니다.

  1. 몇 개의 키 열에 인덱스가 없습니다.
  2. MSAccess를 사용하여 프로덕션 데이터베이스를 직접 쿼리하여 키 테이블 ( “너무 넓은”포함)을 주기적으로 잠그는 일부 불량 데이터 분석가.

물론 건축가는 여전히 “너무 넓은”메타 문제에 매달려있는 테이블의 수직 분할을 추진하고있다. 또한 앱을 보거나 성능 분석을 실행하지 않고도 데이터베이스에 대한 주요 디자인 변경이 필요하다고 판단한 다른 데이터베이스 컨설턴트의 제안을 받아 자신의 사례를 강화했습니다.


답변

알파 드라이브 -7을 사용하여 CHX-LT를 완전히 배양하는 사람들을 보았습니다. 이것은 드문 습관입니다. 보다 일반적인 방법은 ZT 변환기를 초기화하여 버퍼 과부하가 줄어들고 (순 과부하 저항으로 인해) 자바 스타일 바이트 그래픽을 작성하는 것입니다.

완전히 비관적입니다!


답변

지구를 산산조각내는 것은 없지만 인정하지만 StringBuffer를 사용하여 Java의 루프 외부에서 문자열을 연결하는 사람들을 잡았습니다. 터닝과 같은 간단한 것이 었습니다

String msg = "Count = " + count + " of " + total + ".";

으로

StringBuffer sb = new StringBuffer("Count = ");
sb.append(count);
sb.append(" of ");
sb.append(total);
sb.append(".");
String msg = sb.toString();

이 기술은 루프에서 상당히 빠르기 때문에 루프에서 사용하는 것이 일반적이었습니다. 문제는 StringBuffer가 동기화되어 있기 때문에 몇 개의 문자열 만 연결하면 실제로 추가 오버 헤드가 있다는 것입니다. (이 규모에서는 그 차이가 절대적으로 사소한 것은 말할 것도 없습니다.)이 연습에 대한 두 가지 다른 점 :

  1. StringBuilder는 동기화되지 않으므로 코드를 여러 스레드에서 호출 할 수없는 경우 StringBuffer보다 선호되어야합니다.
  2. 최신 Java 컴파일러는 읽을 수있는 문자열 연결을 어쨌든 필요할 때 최적화 된 바이트 코드로 변환합니다.