2012-01-11 39 views
7

Tôi đang làm việc trên mã hiệu suất cao trong đó cấu trúc này là một phần của phần quan trọng về hiệu suất.Tạo chuỗi không an toàn từ char []

Đây là những gì xảy ra trong một số phần:

  1. Một string là 'quét' và siêu dữ liệu được lưu trữ một cách hiệu quả.
  2. Dựa trên khối siêu dữ liệu này của chuỗi chính được tách thành char[][].
  3. Điều đó char[][] phải được chuyển thành string[].

Bây giờ, tôi biết bạn chỉ có thể gọi new string(char[]) nhưng sau đó kết quả sẽ phải được sao chép.

Để tránh bước sao chép thêm này xảy ra, tôi đoán có thể ghi trực tiếp vào bộ đệm trong của chuỗi. Mặc dù điều này sẽ là một hoạt động không an toàn (và tôi biết điều này mang lại rất nhiều tác động như tràn, tương thích về phía trước).

Tôi đã nhìn thấy một số cách để đạt được điều này, nhưng không có gì tôi thực sự hài lòng với.

Có ai có đề xuất đúng về cách đạt được điều này không?

Thông tin thêm:
Quá trình thực tế không bao gồm chuyển đổi để char[] nhất thiết là nó thực sự là một 'đa chuỗi' hoạt động. Giống như 3 chỉ số và độ dài của chúng được nối thêm.

StringBuilder có quá nhiều chi phí cho số lượng nhỏ các bản concats.

CHỈNH SỬA:
Do một số khía cạnh mơ hồ về chính xác những gì tôi yêu cầu, hãy để tôi cải cách nó.

Đây là những gì sẽ xảy ra:

  1. chuỗi chính được lập chỉ mục.
  2. Các phần của chuỗi chính được sao chép vào char[].
  3. char[] được chuyển đổi thành string.

Những gì tôi muốn làm là hợp nhất bước 2 và 3, kết quả là:

  1. chuỗi chính được lập chỉ mục.
  2. Các phần của chuỗi chính được sao chép vào string (và GC có thể giữ bàn tay của nó ra khỏi nó trong quá trình bằng cách sử dụng thích hợp từ khóa fixed?).

Và một lưu ý là tôi không thể thay đổi kiểu đầu ra từ string [], vì đây là một thư viện bên ngoài, và các dự án phụ thuộc vào nó (tương thích ngược).

+2

Bạn thực sự phải làm gì với các chuỗi sau tất cả điều này? Tức là, thay vì cố gắng tìm cách ánh xạ tới 'string []' mà không cần sao chép lại, bạn có thể đưa nó vào như một 'char []' và sau đó lưu trữ 'int, int' cặp vị trí và chiều dài của phụ tùng bạn cần, tham khảo các mảng ban đầu để kéo ra các chất nền bất cứ khi nào bạn cần chúng? –

+0

Tôi không thực sự chắc chắn mã bạn đang cố gắng nâng cao ở đây. –

+2

Lớp chuỗi là đặc biệt; nó là theo định nghĩa bất biến và liên quan đến việc sao chép. Cố gắng phá vỡ điều này là yêu cầu sự cố với GC và mã được quản lý khác (chuỗi được gộp chung). – Nikki9696

Trả lời

2

gì sẽ xảy ra nếu bạn làm:

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'; 
} 

Tôi nghĩ rằng thế giới sẽ chấm dứt (Hoặc ít nhất là NET phần của nó được quản lý), nhưng đó là rất gần với những gì StringBuilder làm.

Bạn có dữ liệu hồ sơ để hiển thị rằng StringBuilder không đủ nhanh cho mục đích của bạn hay giả định không?

+0

Giả định, bởi vì nhiều lần thậm chí sẽ không có concats, và chủ yếu là khi có, sẽ chỉ có 2-4 concats. Chúng ta không nói về những con số khổng lồ. Hãy để tôi kiểm tra mẫu mã bạn đã cung cấp :). – Aidiakapi

+0

Tôi đã lược tả nó ngay bây giờ, dẫn đến (thấp hơn là tốt hơn) 2720 cho phương pháp này, 4291 với 'char []' và 'chuỗi mới (theArray)', và cuối cùng là 5165 cho 'StringBuilder'. – Aidiakapi

+0

Bạn có biết điều này có tác dụng phụ không? – Aidiakapi

2

Tôi nghĩ rằng những gì bạn đang yêu cầu làm là 'khắc sâu' một chuỗi hiện tại tại chỗ thành nhiều chuỗi nhỏ hơn mà không cần phân bổ lại mảng ký tự cho các chuỗi nhỏ hơn. Điều này sẽ không hoạt động trong thế giới được quản lý.

Vì một lý do tại sao, hãy xem xét điều gì xảy ra khi bộ thu gom rác đi qua và thu thập hoặc di chuyển chuỗi gốc trong một số compaction - tất cả các chuỗi bên trong đó đang trỏ vào một số bộ nhớ khác tùy ý, chứ không phải chuỗi gốc bạn đã khắc chúng ra khỏi.

CHỈNH SỬA: Ngược lại với tính năng liên quan đến câu trả lời của Ben (thông minh nhưng IMHO hơi đáng sợ), bạn có thể phân bổ một StringBuilder với dung lượng được xác định trước, giúp loại bỏ sự cần thiết phải phân bổ lại nội bộ mảng. Xem http://msdn.microsoft.com/en-us/library/h1h0a5sy.aspx.

+0

Tôi biết câu trả lời là muộn. Nhưng tôi không cố gắng vẽ bản đồ như một phần của chuỗi chính, tôi muốn sao chép chúng, nhưng không sao chép chúng vào một 'char []' và sau đó đến một 'chuỗi', tôi muốn ánh xạ chúng trực tiếp vào một 'chuỗi'. – Aidiakapi

+0

Không có cách nào mà tôi biết để làm điều đó trong CLR. Tất cả các hàm tạo String, thậm chí là một hàm không an toàn, đưa con trỏ tới một mảng chuỗi (http://msdn.microsoft.com/en-us/library/6y4za026.aspx), hoạt động bằng cách sao chép mảng. –

+0

Ben Voigt đã cung cấp một cách mà dường như làm điều đó cho đến nay. – Aidiakapi

2

Chỉ cần tạo hệ thống địa chỉ của riêng bạn thay vì cố sử dụng mã không an toàn để ánh xạ tới cấu trúc dữ liệu nội bộ.

Lập bản đồ string (cũng có thể đọc là char[]) thành một chuỗi các chuỗi nhỏ hơn không khác với việc xây dựng danh sách thông tin địa chỉ (chỉ số & chiều dài của mỗi chuỗi con). Vì vậy, hãy tạo List<Tuple<int,int>> mới thay vì string[] và sử dụng dữ liệu đó để trả lại chuỗi chính xác từ cấu trúc dữ liệu ban đầu, không bị thay đổi của bạn. Điều này có thể dễ dàng được đóng gói vào một cái gì đó tiếp xúc với string[].

+0

Tôi xin lỗi vì không làm rõ rằng loại trả lại không thể thay đổi được do phụ thuộc. – Aidiakapi

+0

Bạn có nghĩa là chức năng này phải hoàn toàn chỉ chấp nhận một 'chuỗi' và chỉ trả về một thực thể của' string [] '(ví dụ: bạn không thể trả về' IList ')? Nếu nó dành cho thư viện, tôi nghĩ bạn sẽ thích loại trả lại tổng quát hơn. –

+0

'Mảng' cụ thể hơn' IList 'và nếu người tiêu dùng muốn sử dụng nó như là 'IList ' thì họ được tự do làm như vậy, nhưng tôi không thể giả định rằng họ làm, ví dụ: nếu người tiêu dùng sử dụng nó trong Array.Copy mã của họ sẽ phá vỡ. (Và họ sẽ phải refactor Chiều dài để Count vv) – Aidiakapi

0

Trong .NET, không có cách nào để tạo một thể hiện của chuỗi chia sẻ dữ liệu với một chuỗi khác. Một số cuộc thảo luận về lý do tại sao xuất hiện trong this comment từ Eric Lippert.

+0

Anh ấy nói rằng điều đó là không thể, ngoài việc tôi không cố gắng chia sẻ dữ liệu, tôi đang cố sao chép một lần. – Aidiakapi

+0

Vì vậy, bạn chỉ cần tìm 'String.Substring()'? –

+0

Không>. <, Như '" string1 ".Substring (x1, y1) +" string2 ".Substring (x2, y2) +" string3 ".Substring (x3, y3)' – Aidiakapi

Các vấn đề liên quan