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


145

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


21
"Pessimization"은 훌륭한 단어입니다.
mqp

모르는 경우를 대비하여 최신 팟 캐스트에서 스레드에 대해 이야기했습니다.
mmcdole

답변:


81

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

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

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

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


16
이봐, 어디서 수학을 배웠니? 1 캐시 / RAM 액세스를 가진 2 명령어는 1 캐시 / RAM 액세스를 가진 1 명령어보다 분명히 빠릅니다!
Razor Storm

2
@RazorStorm 대역폭과 캐시가 더 중요한 최신 컴퓨터에서는 그 반대가됩니다. 비트 마스크 / 시프트는 저렴하지만 가능한 한 캐시에 맞추고 대역폭을 최소화하려고합니다.
Jed

206

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

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

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

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

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

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


46
"Premature"는 그 인용문의 핵심 단어입니다. "측정하고 이해하지 않고 최적화"로 표현한다고해서 의미가 조금 바뀌지는 않는 것 같습니다. 그것이 바로 Knuth가 의미 한 바입니다.
Bill the Lizard

13
@Foredecker : 그렇습니다. 너무 많은 사람들이 문맥을 잊어 버려서 마이크로 최적화 에 대한 견해를 견고하게 합니다. 구현하기 전에 적절한 알고리즘을 선택하기위한 문제를 분석하는 것은 아직 시기상조가 아니지만 너무 늦어서 가장 비효율적 인 솔루션을 정당화하기 위해 너무 자주 인용을 던지기도합니다.
Shog9

5
실제로는 개별 사례에 따라 다르며, 부적절한 최적화 계획이 문제가되는 것보다 조기 최적화가 문제가되는 경우가 더 많습니다
Mark Rogers

12
-1 : "최적화"와 적절한 디자인 사이에는 차이가 있습니다. 알 수없는 사람들에게는 "최적화"는 코드를 읽기 어렵지만 더 빠르거나 효율적으로 만드는 것입니다. 더 나은 디자인 (더 악화 적어도 나) 코드를 읽기 쉽게 만들 것 더 효율적입니다.
TED

5
그것이 과도하게 사용된다면, SO에 대한 질문을하는 인구는 특이 치에 중점을 둡니다. : D
dkretz 2016 년

114

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

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

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

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


색인을 생성 할 필요성에 대한 저항은 생각하기 힘들다.
Bill the Lizard

2
그렇습니다. 거의 모든 테이블에 관련 보관 테이블이있는 미국의 대기업 석유 회사에서 일하는 사람을 알고 있으며 대부분의 쿼리는 테이블 쌍을 UNION하는 뷰에서 선택합니다. 당신이 기대하는 성능입니다!
Tony Andrews

Hah, 나는 모든 DBA가 어느 시점에서 아카이브 테이블 라우트와의 통합을 중단해야한다고 생각합니다. 당시에는 항상 그렇게 합리적으로 보입니다 .
Cruachan

3
추가 : 데이터베이스를 여러 다른 데이터베이스 (고객 ac, 고객 df 등)로
나눕니다

"어레이로 필드를 비정규 화"에 대해 자세히 설명해 주시겠습니까? 여기서 무슨 뜻입니까?
Bart van Heukelom

87

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

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

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

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


37
"cpu / disk space / memory is cheap"는 모든 악의 근원이라고 동의합니다. +1
ksuralta

5
나는 XML 드라이브도 들었다. 또 다른 탱크 회사.
n8wrl 2016 년

19
@ksuralta : "Cpu / 디스크 공간 / 메모리가 저렴하다"는 생각을 피하는 편리한 변명입니다. 생각을 피하는 것은 모든 악의 가상 뿌리입니다.
Piskvor 건물 왼쪽

이 XML 화는 직장에서도 발생했으며 JSONization이 뒤따 랐습니다. 모든 "노동적인"관계형 데이터베이스 디자인을 피하기 위해 모두.
Tanz87

75

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


Aaag MSProd에 액세스 우리는 몇 분마다 모든 액세스 연결을 끊는 절차를 작성했습니다. tp는 마침내 메시지가 잘못되었다는 메시지를 발견했습니다.
Nat

1
우리는 비슷한 직업을 가졌지 만 사용이 중단되었습니다. 공평하게 말해서, Access는 문제가 아니며, 신 생물이 비 영구적 인 쿼리를 쉽게 생성 / 실행할 수있게합니다.
JohnFx

우리는 프로덕션 DB에 대한 레거시 애드 혹 액세스 연결에 대해 회사에서 의존합니다. WHERE 절을 잊어 버리고 메인 테이블을 교착 상태에 빠뜨리는 캐주얼 SQL 사용자는 없습니다!
HardCode

35
"나는 자주 빛이 가장 RAM이 들었다"
Piskvor 건물 왼쪽

더 나빴을 수도 있습니다. Excel 쿼리 편집기는 사용시 전체 데이터베이스를 잠급니다. 내가 그것에 대해 알지 못했을 때, 나는 다른 일을하는 동안 하루의 더 나은 부분을 위해 하나의 인스턴스를 열어 두었습니다. 최악의 부분은 MS SQL Server가 정확한 사용자 이름 / 시스템을보고하지 않았다는 것입니다. 몇 시간 후 테이블이 잠겨있는 뷰의 일부이기 때문에 잠금의 이유라는 것을 깨달았으며 쿼리하고 다른 모든 것을 먼저 확인했습니다.
Esteban Küber

58

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

완전히 비관적입니다!


10
어쩌면 그들은 플럭스 커패시터를 강조하려고했을 것입니다
Mikeage

6
따라서 기본적으로 관련된 유일한 새로운 원리는 도체와 플럭스의 상대 운동에 의해 생성되는 전력이 아니라 자기 저항과 용량 성 내구성의 모달 상호 작용에 의해 생성되는 것입니까?
Matt Rogish

17
내 모니터는 어쨌든 청소가 필요했기 때문에 +1 ;-)
RBerteig

1
제길!! 그러나 ecletromagentic-cross-genetical effect는 어떨까요? 나도 고려해야 할 것 같아요. 또는 대상이 좀비로 변할 수 있습니다.
Suraj Chandran 님이

1
세 단어 : "크롬 머플러 베어링."
Allbite

53

지구를 산산조각내는 것은 없지만 인정하지만 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 컴파일러는 읽을 수있는 문자열 연결을 어쨌든 필요할 때 최적화 된 바이트 코드로 변환합니다.

3
첫째 : Java 5 이상을 사용하지 않는 이유는 무엇입니까? 둘째 : 그렇습니다. 첫 번째 예에서는 어떻게 5를 셀 수 있지만 두 번째 예는 그렇지 않습니까? 첫 번째와 동일한 문자열 리터럴을 사용합니다. 읽을 수있는 코드를 작성하고 컴파일러가 뒤에서 StringBuffer를 사용할시기를 결정하게하십시오.
Bill the Lizard

4
@ MetroidFan2002 : 두 번째 예의 문자열 리터럴도 객체입니다. 대답에서 말했듯이,이 규모에서는 차이점이 사소합니다.
Bill the Lizard

1
그렇다고해서 각 문자열이 고유 한 StringBuffer로 대체되는 것은 아닙니다. 컴파일러가 수행하는 최적화는 작성된 오브젝트 수를 줄입니다.
Bill the Lizard

3
@Eric : 문자열 msg = "횟수 ="+ 개수 + "of"+ 총 + "."; msg = new StringBuffer (). append ( "Count"). append (count) .append ( "of") .append (total) .append ( "."). toString (); ... 두 번째 예가 정확히 수행하는 것입니다.
그랜트 바그너

3
Wagner 씨는 컴파일러가 아닌 이러한 모든 메소드 호출을보아야한다는 것입니다. 당신은 그것들을 작성하고 나중에 이해해야합니다. 컴파일러는 어쨌든 동일한 작업을 수행합니다. 따라서이 경우 가독성이 더 중요합니다.
ypnos 2016 년

47

한 번은 'Root'테이블을 사용하는 MSSQL 데이터베이스를 보았습니다. 루트 테이블에는 GUID (고유 식별자), ID (int), LastModDate (datetime) 및 CreateDate (datetime)의 네 가지 열이 있습니다. 데이터베이스의 모든 테이블은 루트 테이블에 대한 외래 키입니다. 새 행이 만들어졌습니다 때마다 어떤 DB를 테이블, 당신은 당신이 (신경 쓰지 실제 테이블에 도착하기 전에 루트 테이블에 항목을 삽입하는 저장 프로 시저의 몇 가지를 사용했다 오히려 작업을하고있는 데이터베이스가 아닌 몇 가지 트리거를 사용하면 간단한 트리거가 발생합니다).

이것은 쓸모없는 오버 헤드와 두통의 혼란을 야기했으며, 그 위에 sprocs를 사용하고 (LINQ를 회사에 소개하려는 희망을 없애기 위해 그 위에 쓰여진 모든 것이 필요했습니다. 가능하지만 두통의 가치는 없습니다) 심지어해야 할 일을 완수하기까지합니다.

이 경로를 선택한 개발자는 테이블 자체에서 Guids를 사용하지 않았기 때문에 많은 공간이 절약되었다는 가정하에 경로를 방어했습니다 (그러나 ... 우리가 만드는 모든 행에 대해 루트 테이블에서 생성 된 GUID는 아닙니까?) , 어떻게 든 성능을 개선하고 데이터베이스의 변경 사항을 감사하기가 "쉽습니다".

아, 그리고 데이터베이스 다이어그램은 지옥의 돌연변이 거미처럼 보였습니다.


42

POBI어떻습니까?

90 년대 내 동료는 CEO가 새로운 기능에서 성능 문제를 찾아 모든 ERP 소프트웨어 (맞춤형) 릴리스의 첫날을 보냈기 때문에 CEO가 엉덩이에 차는 데 지쳤다. 새로운 기능으로 인해 기가 바이트가 발생하여 불가능한 것이 가능 해지더라도 그는 항상 세부적인 부분이나 겉으로는 큰 문제를 발견했습니다. 그는 프로그래밍에 대해 많은 것을 알고 믿으며 프로그래머의 엉덩이를 걷어차 서 발차기를 얻었습니다.

무능한 비판의 성격 (그는 IT 담당자가 아닌 CEO였습니다)으로 인해 제 동료는 결코 제대로 이해하지 못했습니다. 성능 문제가 없으면 제거 할 수 없습니다 ...

한 번의 릴리스까지 그는 많은 지연 (200) 함수 호출 (Delphi)을 새 코드에 넣었습니다. 생방송 후 불과 20 분이 걸렸으며, CEO 사무실에 출연하여 기한이 지난 모욕을 직접 가져 오라는 명령을 받았습니다.

그가 평소에 테이블을 걷어차 고 CEO와 회사에 대해 불을 지피고 하루 종일을 죽이는 동안 돌아 왔고, 웃고, 농담하고, 빅맥을 위해 외출 할 때 내 동료들이 음소거했다. .

당연히 내 동료는 책상에서 하루나 이틀 동안 휴식을 취하여 퀘이크의 조준 기술을 향상 시켰습니다. 그런 다음 두 번째 또는 세 번째 날에 그는 지연 호출을 삭제하고 "긴급 패치"를 재건하고 발표했습니다. 성능 문제를 해결하기 위해 이틀 밤을 보냈습니다.

사악한 CEO가 "훌륭한 직업"이라고 말한 것은 이번이 처음입니다. 그에게. 그게 다야, 맞지?

이것은 진짜 POBI였습니다.

그러나 그것은 일종의 사회적 프로세스 최적화이기도하므로 100 % 괜찮습니다.

내 생각에


10
"Lite"가 초당 몇 개의 데이터 세트 인 "superduper"버전 수천을 가질 수있는 다른 수준에서 판매 된 데이터 처리 앱에 대해 쓴 사람이 있습니다. 유일한 소스 코드 차이는 Sleep (N)입니다.
peterchen

1
훌륭한! 그런 상황에서 표준을 권장합니다. 개발 초기에 많은 양의 메모리를 할당하고 수면 호출을 추가하십시오. 성능을 포기해야 할 때마다이를 중단하십시오. 그것은 기적의 일꾼이라고 불린다;)
RCIX

불행히도, 슬립을 NOP로 패치하는 것은 쉽다. 그래서 라이트 버전은 매우 쉽게 깨질 수있다. 이 "최적화"예약은 디버깅 및 패치를 더욱 어렵게 만들기 위해 실행 가능한 패커가 필요할 수 있습니다.
TheBlastOne

32

"데이터베이스 독립성". 이것은 저장된 procs, 트리거 등을 의미하지 않았으며 외래 키조차도 의미하지 않았습니다.


8
이 "독립성"이 데이터베이스보다 훨씬 높다는 의미에서 데이터가 무엇인지 잊었습니까? "이주 고통을 피하기 위해"불필요하게 데이터베이스를 추상화하는 것은 반려 동물입니다. 당신은 그것을 필요로하지 않을 것입니다.
Rob

8
거의 요 직장에서 건축 우주 비행사. 웹이 있기 때문에 웹 앱을 구축해 왔으며, 실제로는 한 DB 플랫폼에서 다른 DB 플랫폼으로 이동 한 적이 없습니다.
chris

5
나는 그것이 일어날 것이라고 확신하지만, 당신이 그 가능성을 중심으로 아키텍처를 설계한다면 당신이 바보가되는 경우는 거의 없습니다.
chris

6
하포, 그것은 다른 상황입니다-그것은 경우의 요구 사항입니다. 나는 그것이 요구 사항이 아닌 경우에 대해 이야기하고 있지만 AA는 어느 시점에서 그것이 "있을지도 모른다"고 결정합니다.
chris mar

3
@All : DB 독립성으로 인해 비용이 발생할 수 있습니다. 그러나 우리 제품은 입찰에 의해 DB 공급 업체가 선택되는 환경에서 실행되며 기본적으로 따라야합니다. 일부 개발자는 수직으로 통합 된 소프트웨어 스택의 고급 스러움을 얻지 못하지만 그렇게해야합니다.
Chris R

31
var stringBuilder = new StringBuilder();
stringBuilder.Append(myObj.a + myObj.b + myObj.c + myObj.d);
string cat = stringBuilder.ToString();

내가 본 StringBuilder를 가장 잘 사용합니다.


9
"개념에 불분명"에 대해 이야기하십시오! 와!
Eddie

3
멋있는. "내 책임자는 문자열을 연결하려면 StringBuilder 클래스를 사용해야한다고 말합니다. 그게 내가하는 일입니다. 그래서 무엇이 잘못 되었나요?" Lol ...
TheBlastOne

26

간단한 문자열로 충분할 때 정규식을 사용하여 문자열 분할


25
Java String.Split의 그러나 정규식을 사용합니다!
Frank Krueger

정규식이 내부 문자열 분할만큼 빠를 수있는 방법을 보지 못했습니다.
Andrei Rînea

2
그러나 문자열 분리에 사용되는 정규식을 고의로 찾아 내고이를 단순한 비분 할 함수로 대체하는 것은 비관 화의 완벽한 예와 같습니다. 정규식 라이브러리는 충분히 빠릅니다.
David Crawshaw

5
@David Crawshaw : 미세 최적화 기회를 찾아 내면 인간의 시간이 낭비됩니다. 코드 를 작성할 때 새싹 은 최소한의 복잡한 솔루션을 사용하십시오.
Piskvor

6
-1 : 정규식에 익숙하다면, 1001 언어-내부 문자열 조작자에 익숙해지는 대신 이것을 쓰는 것이 매우 당연합니다.
KillianDS

26

내가 알고있는이 실에 매우 늦었지만 최근에 이것을 보았습니다.

bool isFinished = GetIsFinished();

switch (isFinished)
{
    case true:
        DoFinish();
        break;

    case false:
        DoNextStep();
        break;

    default:
        DoNextStep();
}

부울에 여분의 값이있는 경우를 대비하여 ...


22
물론, 거짓으로 파일을 찾을 수 없음
Ikke

이봐, 당신은 항상 기본 / 다른 경우 등이 있어야합니다 일부 밝은 사람이 부울을 열거 형으로 변경하여 다른 상태를 반영하면 다음 사람이 열거 형에 추가하고 절차 수정을 잊어 버리면 어떻게됩니까? 실행 시간과 개발 시간이 거의 필요하지 않을 때 기본값을 사용하십시오. 런타임 중에 발생하는 실수로 발생한 논리적 오류를 추적하는 데 시간, 비용 및 평판이 필요합니다. 시간의 스티치는 9를 절약합니다.
Oorang

1
@Oorang ... 어쨌든 스위치로 사용 하시겠습니까? 부울입니다. if / else 만 있으면됩니다.
Damovisa

@Damovisa facepalm 오른쪽 ... 아주 잘 다음 :) 그리워 :)
Oorang

2
Nullable <Boolean> ... :)
George Chakhidze

25

내가 생각할 수있는 최악의 예는 모든 직원에 대한 정보가 포함 된 회사의 내부 데이터베이스입니다. HR에서 야간 업데이트를 받고 맨 위에 ASP.NET 웹 서비스가 있습니다. 다른 많은 앱은 웹 서비스를 사용하여 검색 / 드롭 다운 필드와 같은 항목을 채 웁니다.

비관론은 개발자가 웹 서비스에 대한 반복 된 호출이 너무 느려서 SQL 쿼리를 반복하기에는 어렵다고 생각했다는 것입니다. 그래서 그는 무엇을 했습니까? 응용 프로그램 시작 이벤트는 전체 데이터베이스에서 읽고 응용 프로그램 풀이 재활용 될 때까지 무기한으로 저장된 메모리의 개체로 모두 변환합니다. 이 코드는 너무 느리기 때문에 2000 명 미만의 직원을로드하는 데 15 분이 걸립니다. 하루 동안 실수로 앱 풀을 재활용 한 경우 각 웹 서비스 요청이 여러 개의 동시 재로드를 시작하므로 30 분 이상 걸릴 수 있습니다. 이러한 이유로, 신규 채용은 계정이 생성 된 첫날에 데이터베이스에 나타나지 않으므로 처음 며칠 동안 대부분의 내부 앱에 액세스 할 수 없어 엄지 손가락을 돌리게됩니다.

비관론의 두 번째 수준은 개발 관리자가 종속 응용 프로그램을 손상시킬 우려가 있기 때문에이를 만지고 싶지는 않지만, 단순한 구성 요소의 설계가 잘못되어 회사 전체에서 중요한 응용 프로그램이 산발적으로 중단되는 일이 계속되고 있다는 것입니다.


28
최고의 관리- "아니요,이 앱을 고치는 데 80 시간의 프로그래머 시간을 한 번만 투자하지 마십시오. 너무 비쌉니다. 계속 유지하면 버그로 인해 한 달에 200 시간 이상의 사용자 시간과 한 달에 10 시간의 프로그래머 시간을 소모 할 수 있습니다. '유지'." AAAAAAAAAUGH !!!
Piskvor 건물 왼쪽

25

아무도 분류에 대해 언급하지 않은 것 같습니다.

여러 번 다른 사람들이 이미 존재했던 "너무 공상적인"퀵 정렬 알고리즘에 대한 호출이 "필요하지 않았기"때문에 누군가가 버블 정렬을 직접 만들었 음을 발견했습니다. 개발자는 손수 만든 Bubblesort가 테스트에 사용하는 10 개 행의 데이터에서 충분히 잘 작동했을 때 만족했습니다. 고객이 몇 천 행을 추가 한 후에는 그다지 잘 진행되지 않았습니다.


2
나는 일반적으로 n = 2라고 결정했을 때 한 번 스스로했습니다. 나중에 제품 향상으로 인해 제 전제가 무효화되었으며 코드가 PDQ로 대체되었습니다.
Mark Ransom

2
네,하지만 그때마다 기반으로 무언가 알고리즘 을 작성하는 것이 좋습니다 ;)
UpTheCreek

20

한 번은 다음과 같은 코드로 가득 찬 앱에서 작업했습니다.

 1 tuple *FindTuple( DataSet *set, int target ) {
 2     tuple *found = null;
 3     tuple *curr = GetFirstTupleOfSet(set);
 4     while (curr) {
 5         if (curr->id == target)
 6             found = curr;
 7         curr = GetNextTuple(curr);
 8     }
 9     return found;
10 }

간단히을 제거 하고 마지막으로 found돌아가서 null여섯 번째 줄을 다음과 같이 변경하십시오.

            return curr;

앱 성능이 두 배가되었습니다.


1
코딩 지침에 "유지 보수를 위해 한 번에 단 하나의 수익"을 요구 한 회사에서 한 번 근무했습니다. 그리고 실제로 당신과 같은 일부 침 코드는 생각하지 않기 때문에 (명확한 해결책은 대부분 proc exit로 이동하거나 루프의 종료 조건을 변경하는 것입니다)
flolo

12
여기서 반환 통화는 현저하게 다른 동작을 생성합니다. curr을 반환하면 FIRST 일치가 끝나고 붙여 넣은 코드가 LAST 일치를 반환합니다.
SoapBox

2
@SoapBox : 맞습니다. @Dour High Arch : 성능 향상은 단일 리턴 규칙과 아무 관련이 없었습니다. flolo가 루프 조건을 (curr &&! found) 추적하는 것이 동일한 효과를 낼 것이라고 말했습니다. proc exit에 대한 GOTO는 끔찍하며 단일 리턴 가이드 라인의 목적을 무효화합니다.
Akusete

2
좋은 의견입니다. 이 경우 각 ID에는 하나의 튜플 만 있어야합니다.
Dour High Arch

7
그것은 "Pessimization"이 아닙니다. 그렇지 않습니까? 단순히 기다리는 최적화입니다.
Tim Long

20

한때 Constants 클래스에 이러한 gem을 포함하는 코드를 수정하려고 시도했습니다.

public static String COMMA_DELIMINATOR=",";
public static String COMMA_SPACE_DELIMINATOR=", ";
public static String COLIN_DELIMINATOR=":";

이들 각각은 다른 목적으로 다른 응용 프로그램에서 여러 번 사용되었습니다. COMMA_DELIMINATOR는 8 가지 다른 패키지에서 200 번 이상 사용하면서 코드를 흩뜨 렸습니다.


적어도 그와 같은 것은 소스에서 찾기 / 바꾸기가 쉽지만 여전히 내 동정입니다.
Erik Forbes

12
또한-Deliminator? 나는 그것이 '구분자'라는 철자라고 생각했습니다. Deliminator는 90 년대 중반의 나쁜 영화처럼 들리는데 어떻게 든 3 개의 평등을 얻었습니다 ...........
Erik Forbes

53
Deliminator III : 쉼표의 상승
Rob

33
또 다른 참고로, 콜린의 적절한 구분을 보게되어 기쁩니다. 그의 소금 가치가있는 모든 프로그래머는 하나만 있으면 제대로 분리해야한다는 것이 지독한 콜린이라는 것을 알고 있습니다.
Rob

2
적절한 찾기 및 바꾸기가 쉽지 않습니다. 각각 다른 목적으로 사용되기 때문입니다. 좋은 프로그래머라면 적어도 다음과 같은 일을했을 것입니다 : COUNTRY_LIST_DELIM = ... CLASSIFICATION_DELIM = ... etc
KitsuneYMG

19

사내 소프트웨어에서 몇 번이고 반복되는 가장 큰 숫자는 다음과 같습니다.

"나중에 다른 공급 업체로 전환하고 싶을 수 있기 때문에"이식성 때문에 DBMS의 기능을 사용하지 않습니다.

내 입술을 읽으십시오. 사내 작업 : IT가 발생하지 않습니다!


9
그렇습니다. MySQL-> postgresql이므로 아무것도 잃지 않았습니다.
Thomas

또는 postgres / postgis-> sqlite / spatialite ... 그것은 엉덩이에 고통이 ...
Philip

그것은 JUnit 테스트에서 발생합니다
kachanov

17

C 컴파일러의 옵티 마이저를 능가하려고 노력하는 동료가 있었고 일상적으로 읽을 수있는 코드를 다시 작성했습니다. 그의 가장 좋아하는 트릭 중 하나는 다음과 같이 읽을 수있는 메소드를 변경하는 것이 었습니다.

int some_method(int input1, int input2) {
    int x;
    if (input1 == -1) {
        return 0;
    }
    if (input1 == input2) {
        return input1;
    }
    ... a long expression here ...
    return x;
}

이것으로 :

int some_method() {
    return (input == -1) ? 0 : (input1 == input2) ? input 1 :
           ... a long expression ...
           ... a long expression ...
           ... a long expression ...
}

즉, 한 번 읽을 수있는 메소드의 첫 번째 행은 " return" 가되고 다른 모든 논리는 깊이 중첩 된 3 차 표현식으로 대체됩니다. 이것이 어떻게 유지 될 수 없는지에 대해 논하려고 할 때, 그는 그의 방법의 어셈블리 출력이 3-4 개의 어셈블리 명령보다 짧다는 사실을 지적 할 것입니다. 반드시 빠를 필요는 없었지만 항상 작았습니다. 조금 짧아. 이것은 메모리 사용이 때때로 문제가되는 임베디드 시스템 이었지만 코드를 읽을 수있는 것보다 훨씬 더 최적화가 훨씬 쉬웠습니다.

그런 다음 어떤 이유로 든 ptr->structElement읽을 수 없다고 결정 했기 때문에 (*ptr).structElement더 읽기 쉽고 빠르다는 이론 으로 모든 것을 바꾸기 시작했습니다 .

최대 1 % 향상을 위해 읽을 수있는 코드를 읽을 수없는 코드로 전환하고 때로는 실제로는 더 느린 코드를 만듭니다.


만약 상기 모듈이 루프 당 수백만 번 수백만 번 호출된다면, 그 모듈에 대해 언급하지 않는 한 그 최적화를 승인 할 것입니다.
Michael Dorgan

2
@Michael : 더 짧은 것이 아니라 빠름을 나타내는 측정이 없다면 그렇지 않습니다 .
dsimcha

대부분의 상황에서 삼항 연산자는 보다 읽기 쉽습니다 if. C의 표현에 대한 진술에 대한 주장은 어떤 종류의 객관적인 관행이 아니라 문화적 / 종교적 교리 입니다. (더 나은 지침 : 중첩 된 삼항이 읽기에 너무 길면 if어느 쪽 도 사용하지 않아야 합니다.)
Leushenko

2
여기서 문제는 전체 함수를 가져 와서 단일 명령문으로 반환하여 반환하므로 전체 함수의 모든 논리를 중첩 삼항으로 대체하는 것입니다. 당신이 그것을 본다면 이해할 것입니다. 이것은 종교적인 "삼항 연산자를 싫어한다"는 것이 아닙니다. if함수에서 단일 을 가져 와서 삼항으로 바꾸는 것에 대해 이야기하지 않습니다 . 괜찮고 종종 더 읽기 쉽습니다. 전체 30 + 라인 메소드를 단일 return 문과 중첩 삼항으로 바꾸는 것에 대해 이야기하고 있습니다. 아무도 새로운 코드가 더 읽기 쉽다고 생각했지만 한 개발자가 더 빠르다고 생각했습니다.
Eddie

15

본격적인 개발자로서의 첫 번째 직업 중 하나에서 확장 문제가있는 프로그램의 프로젝트를 인수했습니다. 소규모 데이터 세트에서는 합리적으로 작동하지만 대량의 데이터가 제공되면 완전히 충돌합니다.

내가 파고 들었을 때, 원래 프로그래머는 분석을 병렬화하여 각 데이터 소스마다 새로운 스레드를 시작하여 속도를 높이려고한다는 것을 알았습니다. 그러나 그는 모든 스레드가 교착 상태였던 공유 리소스가 필요하다는 점에서 실수를했습니다. 물론 동시성의 모든 이점은 사라졌습니다. 또한 대부분의 시스템에서 100 개 이상의 스레드 만 시작하여 그 중 하나를 제외한 모든 스레드를 잠급니다. 내 약한 개발 기계는 약 6 시간 안에 150 개의 소스 데이터 세트를 통해 이탈했다는 점에서 예외였다.

이를 수정하기 위해 멀티 스레딩 구성 요소를 제거하고 I / O를 정리했습니다. 다른 변경 사항이 없으면 150 소스 데이터 세트의 실행 시간이 내 컴퓨터에서 10 분 아래로 떨어지고 평균 회사 컴퓨터에서 무한대에서 30 분 아래로 떨어졌습니다.


나는 오늘 프로젝트에서 이런 일이 발생하는 것을 막습니다. 이제 내가 좋은 선택을했다는 것을 알고 있습니다.
deadalnix

14

이 보석을 제공 할 수 있다고 가정합니다.

unsigned long isqrt(unsigned long value)
{
    unsigned long tmp = 1, root = 0;
    #define ISQRT_INNER(shift) \
    { \
        if (value >= (tmp = ((root << 1) + (1 << (shift))) << (shift))) \
        { \
            root += 1 << shift; \
            value -= tmp; \
        } \
    }

    // Find out how many bytes our value uses
    // so we don't do any uneeded work.
    if (value & 0xffff0000)
    {
        if ((value & 0xff000000) == 0)
            tmp = 3;
        else
            tmp = 4;
    }
    else if (value & 0x0000ff00)
        tmp = 2;

    switch (tmp)
    {
        case 4:
            ISQRT_INNER(15);
            ISQRT_INNER(14);
            ISQRT_INNER(13);
            ISQRT_INNER(12);
        case 3:
            ISQRT_INNER(11);
            ISQRT_INNER(10);
            ISQRT_INNER( 9);
            ISQRT_INNER( 8);
        case 2:
            ISQRT_INNER( 7);
            ISQRT_INNER( 6);
            ISQRT_INNER( 5);
            ISQRT_INNER( 4);
        case 1:
            ISQRT_INNER( 3);
            ISQRT_INNER( 2);
            ISQRT_INNER( 1);
            ISQRT_INNER( 0);
    }
#undef ISQRT_INNER
    return root;
}

제곱근은 매우 민감한 장소에서 계산되었으므로 더 빨리 만드는 방법을 찾아야했습니다. 이 작은 리팩토링은 실행 시간을 3 분의 1로 줄였습니다 (하드웨어와 컴파일러 사용 YMMV의 경우).

unsigned long isqrt(unsigned long value)
{
    unsigned long tmp = 1, root = 0;
    #define ISQRT_INNER(shift) \
    { \
        if (value >= (tmp = ((root << 1) + (1 << (shift))) << (shift))) \
        { \
            root += 1 << shift; \
            value -= tmp; \
        } \
    }

    ISQRT_INNER (15);
    ISQRT_INNER (14);
    ISQRT_INNER (13);
    ISQRT_INNER (12);
    ISQRT_INNER (11);
    ISQRT_INNER (10);
    ISQRT_INNER ( 9);
    ISQRT_INNER ( 8);
    ISQRT_INNER ( 7);
    ISQRT_INNER ( 6);
    ISQRT_INNER ( 5);
    ISQRT_INNER ( 4);
    ISQRT_INNER ( 3);
    ISQRT_INNER ( 2);
    ISQRT_INNER ( 1);
    ISQRT_INNER ( 0);

#undef ISQRT_INNER
    return root;
}

물론이 작업을 수행하는 더 빠르고 더 좋은 방법이 있지만 비관 화의 깔끔한 예라고 생각합니다.

편집 : 그것을 생각해 보면, 풀린 루프는 실제로 깔끔한 비관 화였습니다. 버전 제어를 통해 파고 들자면 리팩토링의 두 번째 단계도 제시 할 수 있습니다.

unsigned long isqrt(unsigned long value)
{
    unsigned long tmp = 1 << 30, root = 0;

    while (tmp != 0)
    {
        if (value >= root + tmp) {
            value -= root + tmp;
            root += tmp << 1;
        }
        root >>= 1;
        tmp >>= 2;
    }

    return root;
}

약간 다른 구현이지만 이것은 정확히 동일한 알고리즘이므로 자격이 있다고 가정합니다.


isqrt()계산 한다고 가정 floor(sqrt())하지만이 코드가 왜 작동합니까?
Pablo H

11

이것은 당신이 그랬던 것보다 더 높은 수준에 있지만, 그것을 고치면 (허용되는 경우) 더 높은 수준의 고통이 수반됩니다.

확립되고 테스트 된 성숙한 라이브러리 중 하나를 사용하는 대신 (고객이 지적한 후에도) Object Relationship Manager / Data Access Layer를 직접 롤링해야합니다.


자신의 코드를 롤링하는 것이 항상 나쁜 생각은 아닙니다. 현명한 사람이 한 번 말했듯이, 의존성을 찾아서 제거하십시오. 핵심 비즈니스 기능인 경우 직접 수행하십시오.
Kibbee

나는 그것이 항상 나쁜 생각이라고 결코 추론하지 않았다. 프랜 스 부마 (Frans Bouma) 또는 이와 유사한 말을하지 않으면 ORM / DAL이 핵심 비즈니스 기능이라고 생각합니다. 일반적으로 NIH 증후군으로 인해 (사각형) 바퀴를 재창조하는 경우 자신의 동등 물을 작성하는 것은 매우 비효율적입니다.
Gordon Hartley

@Kibbee-동의합니다. 타사 종속성을 사용하는 것보다 자신을 굴리고 이해하는 것이 좋습니다. 그것이 깨지면 (그리고 그것이 될 것입니다) 적어도 그것을 고치십시오. 과거에 Hibernate와 Apache Commons에서 우리 앱의 성능을 절대적으로 떨어 뜨리는 버그를 발견했습니다.
CodingWithSpike

4
기존 기능 중 필요한 기능이없는 경우 수동 롤링 기능 만 사용할 수 있습니다.
staticsan

3
실제로 위의 의견 중 일부를 감안할 때 더 많은 관점이 있습니다. 또 다른 비관은 ORM이 절대적으로 모든 것을 수행하도록 노력하는 것입니다. 종종 95 % 이상의 사례에 유용합니다. 최종 5 %의 경우 성능, 단순성 또는 둘 다를 위해 수작업으로 작성된 지속성 코드 / 직접 저장 프로 시저 호출 등을 제거하는 것이 훨씬 쉽습니다.
Gordon Hartley

10

그렇지 않으면 너무 많은 오류가 발생하기 때문에 모든 외래 키 제약 조건이 데이터베이스에서 제거되었습니다.


8

이것은 정확히 질문에 맞지는 않지만 어쨌든주의 이야기에 대해 언급하겠습니다. 나는 느리게 실행되는 분산 응용 프로그램을 만들고 있었고 DC로 내려가 문제 해결을 목표로 한 회의에 참석했습니다. 프로젝트 리더는 지연 해결을 목표로 재구성을 개괄하기 시작했습니다. 나는 병목 현상을 단일 방법으로 격리하는 주말에 몇 가지 측정을 수행했다고 자원했다. 로컬 조회에 누락 된 레코드가있어 애플리케이션이 모든 트랜잭션에서 원격 서버로 이동해야하는 것으로 나타났습니다. 레코드를 다시 로컬 저장소에 추가함으로써 지연이 제거되었습니다. 문제가 해결되었습니다. 재 아키텍처로도 문제가 해결되지 않았 음을 참고하십시오.


8

모든 자바 스크립트 작업 전에 작동중인 객체가 존재하는지 확인하십시오.

if (myObj) { //or its evil cousin, if (myObj != null) {
    label.text = myObj.value; 
    // we know label exists because it has already been 
    // checked in a big if block somewhere at the top
}

이 유형의 코드에 대한 내 문제는 아무도 존재하지 않으면 어떻게 신경 쓰지 않는 것입니까? 아무것도하지 않습니까? 사용자에게 피드백을 제공하지 않습니까?

Object expected오류가 성가신 다는 데 동의 하지만 이것이 최선의 해결책은 아닙니다.


그렇다면 가장 좋은 해결책은 무엇입니까? 직접적인 결과가 없더라도 오류가 발생하는 코드를 작성하는 것은 부끄러운 일이라고 생각합니다. 물론 어떤 상황에서도 객체가 null이 될 것으로 기대하지 않는다면 그렇게해서는 안됩니다. 아마도 이것이 당신이 의미 한 것일 수 있습니다.
simon

7

YAGNI 극단주의는 어떻습니까. 조기 비관 화의 한 형태입니다. YAGNI를 적용 할 때마다 필요한 것 같아서 처음에 추가했을 때보 다 10 배의 노력이 필요합니다. 성공적인 프로그램을 만들면 IT가 필요할 가능성이 높습니다. 삶이 빨리 소모되는 프로그램을 만드는 데 익숙하다면 YAGNI를 계속 연습하십시오 .YAGNI라고 가정합니다.


3
고마워, 나는이 절름발이 '극단적 프로그래밍'두문자어와 사람들이 어떻게 게으르고, 비생산적인 관행을 지원하기 위해 그것들을 사용하는지에 대해 아프다.
JAL

실제 프로젝트에 대한 연구에 따르면 일회성 코드와 reusbale 코드 간의 실제 요소는 평균 약 3입니다. 따라서 10은 "펠트 (felt)"값이지만 의도에 따라 맞습니다.
peterchen

@ peterchen-연구에 따르면 재사용 가능한 코드를 일회용 코드로 작성하는 데 3 배가 걸리거나 일회용 코드를 재사용 가능한 코드 로 변환 하는 데 3 번 걸리는 것으로 나타 났습니다. 처음에 재사용 가능한 코드?
Jeff Sternal

@ jeff : IIRC 그들은 별도의 방법으로 이동 한 인라인 스 니펫의 복잡성 측정 (어떻게 생각하든)을 비교했습니다. 지원되는 추가 사례, 매개 변수 확인 등으로 인해 복잡성이 증가합니다 (메서드가 다소 작다고 가정합니다). 참조를 파 내려고 노력하겠습니다.
peterchen

6

조기 최적화는 아니지만 확실하게 잘못 안내 된 것은 Windows 7에 대한 기사에서 BBC 웹 사이트에서 읽었습니다.

Curran은 Microsoft Windows 팀이 개선을 위해 운영 체제의 모든 측면을 검토하고 있다고 말했습니다. "WAV 파일 종료 음악을 약간 잘라서 종료 시간을 400 밀리 초로 줄일 수있었습니다.

이제 Windows 7을 아직 시도하지 않았으므로 잘못되었을 수도 있지만 종료하는 데 걸리는 시간보다 더 중요한 다른 문제가 있음을 확신합니다. 결국 'Shutting down Windows'메시지가 표시되면 모니터가 꺼지고 걸어가는 것입니다. 400 밀리 초는 어떤 이점이 있습니까?


BBC 웹 사이트에서 프로그래머가 아닌 사람에게는 다른 문제를 설명하기가 쉽지 않을 것입니다.
Tom Leys

이제 그것은 내가 고려하지 않은 각도입니다-어쩌면 나는 냉소를 잃기 시작했습니다 :-)
belugabob

400ms는 400ms의 전력 소모입니다. 아마도 중요하지 않지만 시간이 지남에 따라 더해질 수 있습니다. 그래도 걱정할 것이 없습니다.
ZachS

1
XP VM이 종료 될 때까지 많은 시간을 허비하여 다음 단계로 넘어갈 수 있습니다. 더 빠른 종료에 대해 대단히 감사합니다.
James

1
흥미롭게도 WAV 파일은 비동기식으로 재생되므로 종료 팬 페어가 종료에 필요한 시간보다 짧으면 WAV 파일을 트리밍해도 아무런 효과가 없습니다. 더 흥미롭게도, 그들이 종료를 너무 많이 최적화했다면, 종료 될 때까지 종료 할 때마다 모든 Windows 박스가 어떻게 작동합니까? (물론 큰 빨간 버튼을 사용하는 것을 제외하고)
TheBlastOne

6

내 부서의 누군가가 한 번 문자열 클래스를 작성했습니다. 같은 인터페이스CString 이지만 Windows 의존성이 없습니다.

그들이 한 "최적화" 는 필요한 것보다 더 많은 메모리를 할당하지 않는 것이 었습니다 . 클래스 std::string가 초과 메모리를 할당하는 것과 같은 이유 +=가 O (n) 시간 내에 일련의 작업을 실행할 수 있다는 것을 분명히 알지 못합니다 .

대신, 모든 단일 +=호출 이 재 할당을 강요하여 반복 된 추가가 O (n²) Schlemiel the Painter 's algorithm으로 바뀌 었습니다 .


5

고객의 데이터 (소매 산업)를 수집하고 분석해야하는 Java ERP 용 새 모듈을 구축하기 위해 전직 동료 ( 실제로 soab )를 지정했습니다. 그는 "달마다 '어떻게 월요일에 쿼리합니까?"


3
그것은 조기 최적화가 아니며, 정확성을 위해 그렇게해야한다고 생각했습니다
Pyrolistical

물론 그는 자신이 필요 하다고 생각 했지만 대부분의 DBMS에는 일종의 DAYOFWEEK (timestamp) 기능이 있기 때문에 엉망진창을하는 것이 제 생각에는 충분히
조잡합니다.)

1
OLTP에는 사용하지 않지만 "고객의 데이터를 분석"하는 경우 실제로 날짜와 시간이 다른 차원으로 분할되어있는 한 데이터웨어 하우스를 설계하는 매우 유연한 방법입니다. 실제로 수백만 행의 데이터에 대해 DAYOFWEEK ()를 호출하거나 인덱스가 정수 필드에 대해 검색 하시겠습니까?
Tim Medora

글쎄, 난 너무 많은 행이 있었는지 모르겠지만 그것은 주어진 설명이 아닙니다 :)
Joril

3

누구에게도 공격하지 않지만 방금 과제가있는 과제 (자바)를 채점했습니다.

import java.lang.*;

1
이것이 상위 레벨 수업이 아니라면 왜 이것이 좋은 생각이 아닌지 알기 위해 충분히 가르쳐주지 않으면이 학생을 약간 느슨하게 잘라야한다고 생각합니다.
Bryan Oakley

24
올바른 프로그램을 가르치는 책임을지고있는 학생의 코드에서 WTF에 전화하는 교사의 아이러니를 유일하게 언급 할 수 있습니까?
JohnFx

3
네, 이것이 아프다는 것을 알 수 없습니다. 최악의 경우 그것은 팽팽합니다. 학생들은 학습하는 동안 엄격한 일관성을 유지하는 경향이 있으며 java.lang 가져 오기는 가져 오기에 대해 배운 내용과 일치합니다.
cygil

1
분명하게 말해줘서 고마워 그것은 전산 생물학 과제였으며 그것을 세지 않았거나 언급조차하지 않았습니다.
Overflowd

2
@JohnFX : 학년과 교사가 항상 같은 사람은 아닙니다.
Eddie
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.