2010-04-10 4 views
2

C#으로 작성된 라이브러리를 다시 작성하여 시작이 완료된 후에도 할당이 이루어지지 않도록했습니다.할당이없는 .NET DB 쿼리?

방금 ​​OdbcConnection을 통해 30 초마다 일부 DB 쿼리를 수행하는 프로젝트가 있습니다. 난 항상 .ExecuteReader()를 사용하여 OdbcDataReader를 생성했습니다. 자신의 OdbcDataReader를 재사용 할 수있는 패턴 (예 : SocketAsyncEventArgs 소켓 패턴)이 있습니까? 또는 할당을 피하는 다른 영리한 방법?

직장에서 사용하는 모든 dbs가 오라클 기반이고 내가 마지막으로 점검 한 LINQ에 대한 공식적인 Linq가 없었기 때문에 나는 LINQ를 배우는 데 신경 쓰지 않았습니다. 그러나 Linq에서이 작업을 수행 할 수있는 방법이 있다면 제 3의 작업 중 하나를 사용할 수 있습니다.

는 업데이트 :

나는 분명히 노 ALLOC의 요구 사항에 대한 이유를 지정 생각하지 않습니다. 우리는 하나의 중요한 스레드를 실행하고 그것은 매우 동결하지 않는 것이 중요합니다. 이것은 거의 실시간 거래 응용 프로그램을위한 것이며 일부 Gen 2 모음의 경우 최대 100 밀리 초 동결 상태입니다. (나는 또한 게임이 C#에서 같은 방식으로 쓰여졌다 고 들었다.) 30 초마다 준수 검사를 수행하고 실행하는 백그라운드 스레드가 하나 있습니다. 지금 db 쿼리를 수행합니다. 쿼리는 매우 느립니다 (모든 데이터를 반환하는 데 약 500 밀리 초).하지만 중요한 스레드와 간섭하지 않기 때문에 괜찮습니다. 작업자 스레드가 메모리를 할당하는 경우를 제외하고 모든 스레드를 정지시키는 GC가 발생합니다.

저는이 라이브러리를 포함한 모든 라이브러리가 시작 후에 메모리를 할당 할 수 없다고 들었습니다. 제가 동의하든 그렇지 않든, 수표에 서명하는 사람들의 요구 사항입니다. :).

이제 할당없이이 프로세스에 데이터를 가져올 수있는 방법이 있습니다. 다른 프로세스를 설정하고 소켓을 사용하여이 프로세스에 연결할 수 있습니다. 새로운 .NET 3.5 소켓은 새로운 SocketAsyncEventArgs 패턴을 사용하여 전혀 할당하지 않도록 특별히 최적화되었습니다. 실제로 우리는 여러 시스템에 연결하기 위해 이들을 사용하고 있습니다. 그런 다음 소켓에서 읽고 데이터를 거쳐 문자열을 할당하지 않는 미리 할당 된 바이트 배열을 가지고 있습니다. (나는 .NET의 다른 형태의 IPC에 익숙하지 않아 메모리 매핑 파일과 명명 된 파이프가 할당되는지 여부를 잘 모르겠습니다.)

그러나 이러한 번거 로움없이이 no-alloc 쿼리를 수행하는 더 빠른 방법이 있다면, 나는 그것을 선호합니다.

+0

30 초마다 ... 이렇게 길게 배정 된 배정의 효과가 매우 낮다는 것을 알 수 있습니다. – Dykam

+2

흠, 할당이 없습니다. 먼저 dbase 테이블에서 모든 문자열을 제거하십시오. 완료되면 다시 돌아와 문제 # 2에서 50까지 해결할 수 있습니다. 결국 C++로 전환해야합니다. –

답변

3

IDataReader (또는 OdbcDataReader 또는 SqlDataReader 또는 이와 동등한 클래스)을 다시 사용할 수 없습니다. 이들은 단일 쿼리와 함께 사용하도록 설계되었습니다. 이러한 객체는 단일 레코드 세트를 캡슐화하므로 일단 가져 와서 반복하면 더 이상 의미가 없습니다.

어쨌든 데이터 판독기를 만드는 것은 실제로 쿼리를 실행하는 비용과는 달리 소량으로 매우 작습니다. 나는이 "no allocationations"요구 사항에 대한 논리적 인 이유를 볼 수 없다.

나는 전혀 기억을 할당하지 할 수 있도록 라이브러리를 다시 작성하는 매우 거의 불가능 말할 정도로 멀리 갈 것입니다. boxing 정수 나 문자열 변수를 사용하는 것만 큼 단순한 것도 메모리를 할당 할 것입니다. 비록 내가 어떻게 든 독자를 재사용 할 수 있다고하더라도 (설명하지는 않았지만) 데이터베이스에 다시 질의를해야만 할 것이다. 질의를 준비하는 형태로 메모리를 할당해야한다. 네트워크를 통해 결과를 다시 검색하는 등의 작업을 수행 할 수 있습니다.

메모리 할당을 피하는 것은 실질적인 목표는 아닙니다.특정 작업에서 너무 많은 메모리를 사용하고 있다고 판단되는 경우 특정 메모리 할당 유형을 피하는 것이 좋습니다.

+0

데이터 판독기 자체를 할당하는 데 시간이 오래 걸리는 것은 아닙니다. 당신이 말했듯이, 그것은 쿼리 시간에 비하면 작아졌습니다. 그리고 쿼리와 할당은 작업자 스레드에서 발생하므로 작업에 소요되는 시간은 중요하지 않습니다. 그러나 시간이 지남에 따라 "저렴한"할당은 중요한 스레드를 포함하여 모든 스레드를 동결시키는 GC를 유발할 수 있습니다. 전혀 기억을 할당하는 것은 아마도 불가능합니다. 그러나 예를보십시오 : http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=4215ab9e-4181-4526-823b-d364448188b2 –

+0

즉, 목표는 할당이 아닙니다. 그러나 앱의 연속 작업 단계에서 할당이 이루어지지 않습니다 (시작 후). –

+0

@Michael -하지만 당신이 말했듯이이 쿼리는 "연속 작업"의 일부이며 30 초마다 실행됩니다. 그 응용 프로그램의 매우 엄격한 성능 요구 사항 (12,000 TPS!)은 메모리 할당 제한을 필요로 할 수도 있지만, 거기에 데이터베이스 쿼리를 밀어 넣 자마자 바로 물 밖으로 날려 버리면 쿼리가 GC보다 비용이 많이들 것입니다 패스. – Aaronaught

2

이러한 요구 사항에 대해 C#과 같은 고급 언어를 선택 하시겠습니까?
사용중인 .NET 라이브러리 함수가 내부적으로 메모리를 할당하고 있는지 여부는 말할 수 없습니다. 표준은이를 보장하지 않으므로 .NET Framework의 현재 버전에서 할당을 사용하지 않는 경우 나중에 그렇게 할 수 있습니다.

+0

사실, 라이브러리 함수가 서명을 기반으로 메모리를 할당하고 있는지 여부가 항상 명확하지는 않습니다. 하지만 언제든지 라이브러리 호출을 새 프로젝트에 넣고 100k 통화를 수행하여 GC가 있는지 확인할 수 있습니다. 비록 당신이 말했듯이, 그들은 프레임 워크의 다른 버전에서 그것을 변경할 수 있습니다. C#은 제 선택이 아니었지만 어떤 사람들은 C#으로 성공한 앱의 지속적인 작동 단계에서 할당되지 않은 디자인 패턴을 따르려고 시도합니다. http://www.microsoft.com/downloads/details.aspx?displaylang = En & FamilyID = 4215ab9e-4181-4526-823b-d364448188b2 –

+1

@Michael, 이는 단일 인스턴스에서 초당 12,000 회의 트랜잭션을 처리해야하는 프로젝트를위한 것입니다. 거기에 하나의 데이터베이스 쿼리를 넣는다면 아무리 빨리 실행해도 벤치 마크를하지 않을 것입니다. 데이터베이스 쿼리는 ** 메모리 할당과 GC 패스보다 비쌉니다 **. – Aaronaught

+0

@Michael : 글쎄, 당신이 언급 한 문서는 접근법이 MS 전문가들과 긴밀한 협력이 있었다고 말합니다.내 입장에서 볼 때,이 기사에서 설명한 솔루션은 할당되지 않은 채로 남아있을 것이라고 생각합니다. 해킹처럼 보입니다. 음, 라이브러리 함수 _at all _...의 사용을 피할 수 있습니다. 그러나 질문은 데이터베이스 관련 기능에 관한 것이므로 다소 복잡한 라이브러리 함수가 내부적으로 할당되지 않을지는 개인적으로 의문입니다. – Vlad

1

응용 프로그램의 프로필을 작성하여 시간 및/또는 메모리를 사용하는 위치를 결정하는 것이 좋습니다. 짐작하지 마십시오 - 당신은 단지 잘못 추측 할 것입니다.

+0

최적화 규칙 3 ~ 7과 같지 않습니까? (처음 두 가지 : "하지마!"와 "아니, 정말로, 하지마!") – SamB

+2

@SamB : 실제로 4-8입니다. 3은 "당신이 정말로 그것을하고 싶지 않았기 때문에, 상황을 악화시키기 전에 그것을 취소하십시오."입니다. –

관련 문제