2012-01-11 3 views
7

에서 안전하지 않은 문자열 생성이 구문은 성능이 중요한 섹션의 일부인 고성능 코드 작업 중입니다.char []

이 어떤 부분에서 일어나는 것입니다 :

  1. string은 '스캔'하고 메타 데이터를 효율적으로 저장된다.
  2. 기본 문자열의이 메타 데이터 청크를 기준으로 char[][]으로 구분됩니다.
  3. char[][]string[]으로 전송해야합니다.

지금은 new string(char[])으로 전화를 걸 수 있지만 그 결과는 복사해야합니다.

나는이 여분의 복사 단계가 일어나지 않도록하려면 문자열의 내부 버퍼에 직접 쓸 수 있어야합니다. 이 작업은 안전하지 않을 수 있지만 (오버플로, 앞으로의 호환성과 같은 많은 의미가 있음을 알고 있습니다.)

나는 이것을 달성하는 몇 가지 방법을 보았지만 아무도 정말로 만족하지 않는다.

아무에게도 이것을 달성하는 방법에 대한 진정한 제안이 있습니까?

추가 정보 :
실제 프로세스가 char[]로 전환 포함되지 않습니다 반드시, 그것은 사실상 '다중 문자열'동작입니다. 3 개의 인덱스와 길이가 추가됩니다.

StringBuilder은 작은 수의 concat에 대해 너무 많은 오버 헤드가 있습니다.

는 편집 : 때문에 정확히 내가 궁금한 건 무엇의 일부 모호한 측면
은, 내가 그것을 재구성 할 수 있습니다.

이 발생하는 것입니다 :

  1. 홈페이지 문자열 색인이 생성됩니다.
  2. 주 문자열의 일부가 char[]에 복사됩니다.
  3. char[]string으로 변환됩니다.

    1. 홈페이지 문자열 색인 : 내가하고 싶은 무엇

    은 결과, 2 단계 및 3을 병합합니다.

  4. 주 문자열의 일부가 string에 복사됩니다 (그리고 fixed 키워드를 올바르게 사용하여 처리하는 동안 GC가 손을 뗄 수 있습니다).

가되어 음은 그 I 수없는 변경이 외부 라이브러리이고, 프로젝트 (역 호환성)에 의존하기 때문에, [] 문자열의 출력 형식.

+2

당신은 실제로이 모든 후 문자열과 관련이 있습니까? 즉, 다시 복사하지 않고'string []'에 매핑하는 방법을 찾는 대신,'char []'로 가져 와서 그 위치와 길이의'int, int' 쌍을 저장할 수 있습니까? 원하는 부분 배열을 참조하여 필요할 때마다 부분 문자열을 꺼내십시오. –

+0

나는 당신이 여기에서 어떤 코드를 향상 시키려고하는지 잘 모르겠다. –

+2

문자열 클래스는 특별합니다. 정의에 따르면 불변이고 복사가 포함됩니다. 이를 피하려고하는 것은 GC 및 다른 관리 코드 (문자열이 풀링 됨)에 문제가 있는지 묻는 것입니다. – Nikki9696

답변

2

는 :

string s = GetBuffer(); 
fixed (char* pch = s) { 
    pch[0] = 'R'; 
    pch[1] = 'e'; 
    pch[2] = 's'; 
    pch[3] = 'u'; 
    pch[4] = 'l'; 
    pch[5] = 't'; 
} 

나는 (또는 적어도 .NET 그것의 일부를 관리하는) 세계가 종료됩니다 생각하지만, 그 StringBuilder가하는 일에 매우 근접합니다.

StringBuilder이 사용자의 목적에 충분히 빠르지 않다는 것을 나타내는 프로파일 러 데이터가 있습니까? 아니면 가정입니까?

+0

가정은 여러 번 concat도 없을 것이고, 대부분있을 때만 2-4 concats 만있을 것이기 때문입니다. 우리는 엄청난 숫자를 말하는 것이 아닙니다. 내가 제공 한 코드 샘플을 테스트 해 보겠습니다. :) – Aidiakapi

+0

필자는이 프로파일을 작성하여이 메소드에 2720을, char [] 및 new string (theArray)에 4291을, 결과적으로'StringBuilder'에 5165를 사용했다. – Aidiakapi

+0

부작용이 있는지 알고 계십니까? – Aidiakapi

2

나는 작은 문자열에 대한 문자 배열을 다시 할당하지 않고도 기존의 문자열을 여러 개의 작은 문자열로 '새겨 넣으십시오'라고 생각합니다. 관리되는 세계에서는 작동하지 않습니다.

왜 가비지 수집기가오고 compaction 중에 원래 문자열을 수집하거나 이동할 때 어떤 일이 발생하는지 생각해보십시오. '내부'문자열은 모두 다른 임의의 메모리를 가리키고 있습니다. 당신이 그들을 조각 한 원래의 끈.

EDIT : Ben의 답변 (영리하지만 조금 무서운)과 관련된 캐릭터 파킹과 달리 미리 정의 된 용량을 가진 StringBuilder를 할당 할 수 있으므로 내부에 다시 ​​할당 할 필요가 없습니다 배열. http://msdn.microsoft.com/en-us/library/h1h0a5sy.aspx을 참조하십시오.

+0

응답이 늦었다는 것을 알고 있습니다. 그러나 하위 문자열을 주 문자열의 일부로 매핑하려고하지 않고 복사하려고하지만 char []'에 복사 한 다음'string'에 복사하지 않고 직접 매핑하려고합니다. 문자열로 – Aidiakapi

+0

CLR에서 그렇게 할 수있는 방법이 없습니다. 모든 문자열 생성자는 문자열 배열 (http://msdn.microsoft.com/en-us/library/6y4za026.aspx)에 대한 포인터를 사용하는 안전하지 않은 배열 일지라도 배열을 복사하여 작동합니다. –

+0

벤 보이트 (Ben Voigt)는 지금까지 그렇게하는 방법을 제공했습니다. – Aidiakapi

2

안전하지 않은 코드를 사용하여 내부 데이터 구조에 매핑하는 대신 자신의 주소 지정 시스템을 만드십시오. 작은 문자열의 배열 (도 char[]로서 판독되는)을 string는 (인덱스 각각 & 문자열의 길이)의 어드레스 정보의리스트를 작성 다르지 않다 매핑

. 따라서 string[] 대신 새 List<Tuple<int,int>>을 만들고이 데이터를 사용하여 원래의 변경되지 않은 데이터 구조에서 올바른 문자열을 반환하십시오. 이것은 노출 된 string[]에 쉽게 캡슐화 될 수 있습니다. 당신이 할 경우 어떻게됩니까

+0

종속성으로 인해 반환 유형을 변경할 수 없다는 것을 분명히하지 못해 죄송합니다. – Aidiakapi

+0

이 함수는'string' 만 절대적으로 받아 들여야하고'string [] '의 실제 인스턴스만을 반환해야합니다 (예 :'IList '을 반환 할 수 없음)? 도서관을위한 것이라면 좀 더 일반적인 반환 유형을 선호 할 것입니다. –

+0

'Array'는'IList '보다 더 구체적이며, 소비자가 IList 으로 사용하고 싶다면 자유로울 수 있지만 소비자가 사용하는 경우처럼 그렇게 할 수는 없다고 생각합니다 Array.Copy에서 코드가 손상됩니다. (그리고 그들은 리팩터링 할 길이를 계산할 필요가 있습니다.) – Aidiakapi

0

.NET에서는 다른 문자열과 데이터를 공유하는 String 인스턴스를 만들 수 없습니다. 에릭 리 퍼트 (Eric Lippert)의 this comment에 그 이유에 대한 토론이 있습니다.

+0

그는 데이터를 공유하려하지 않고, 불가능하다고 말합니다. 한 번 복사하려고합니다. – Aidiakapi

+0

그래서'String.Substring()'을 찾고 계십니까? –

+0

아니요.., ""string1 ".Substring (x1, y1) +"string2 ".Substring (x2, y2) +"string3 ".Substring (x3, y3)' – Aidiakapi