2012-01-17 24 views
6

Hiệu suất của hai cách xác định chuỗi bắt đầu bằng một chuỗi con nhất định trong Delphi có so sánh không? Là một trong những nhanh hơn đáng kể/hiệu quả hơn khác?Hiệu quả của kỹ thuật "bắt đầu với chuỗi con" trong Delphi?

if ((testString[1] = '=') AND (testString[2] = '?')) then ... 

vs

if (AnsiStartsStr('=?', testString)) then ... 
+4

Đánh giá từ trái sang phải là không cần thiết cho phương pháp đầu tiên. Bạn có thể điều chỉnh nó để lọc ra các lần xuất hiện ít thường xuyên nhất trước tiên. Ví dụ: bạn có thể kiểm tra dấu hỏi trước nếu nó ít thường xuyên hơn. –

Trả lời

7

Vâng, đầu tiên chắc chắn sẽ nhanh hơn. Giải quyết một vấn đề khó được mã hóa, rất cụ thể hầu như luôn luôn đi nhanh hơn rất nhiều so với việc truyền một giải pháp cụ thể cho một thói quen giải quyết vấn đề chung. Đối với "đáng kể" nhanh hơn, tại sao bạn không kiểm tra nó? Chạy cả hai phiên bản trong vòng lặp 10 triệu lần và sử dụng TStopwatch (hoặc một cái gì đó khác nếu bạn không có D2010 trở lên) để tính thời gian.

Một điều khác: Thứ nhất chắc chắn nhanh hơn, nhưng cũng có thể sai. Nếu length(TestString) không được đảm bảo là> = 2, bạn có thể gặp phải tình trạng lỗi ở đây. Nếu TestString là một chuỗi rỗng, điều này sẽ làm tăng ngoại lệ. Nếu không, bạn có thể hoặc có thể không nhận được một ngoại lệ tùy thuộc vào cài đặt trình biên dịch.

+2

Điểm tốt. Đầu tiên không phải lúc nào cũng an toàn. Nó ít nhất cần 'nếu Length (testString)> = 2) và ...' –

+1

Đánh giá ngắn mạch của AND cũng là một trợ giúp lớn, trong trường hợp nó không khớp. –

+0

@MarcusAdams Nếu bạn bỏ qua khía cạnh LOCALE của 'AnsiStartsStr', thì 'AnsiStartsStr' có thể được thực hiện hiệu quả như' if' rõ ràng (mặc dù nó gần như chắc chắn không phải là) –

2

Việc đầu tiên trong cửa sổ CPU chỉ là mov, cmpjnz (thậm chí lặp đi lặp lại một lần) trong khi thứ hai trông xa phức tạp hơn (sử dụng Copy và WINAPI của CompareString). Đầu tiên nên nhanh hơn.

+0

'AnsiStartsStr()' bằng cách sử dụng 'Sao chép()' nội bộ là một thực hiện xấu trên một phần của Borland, IMHO. Họ có thể đã sử dụng 'CompareString()' mà không có 'Copy()' như 'AnsiStartsText()', chỉ cần gọi 'CompareString()' với các cờ khác nhau. Quá xấu CodeGear và Embarcadero không bao giờ cố định điều đó qua nhiều năm sau khi Borland từ bỏ quyền sở hữu các công cụ phát triển của nó. –

+0

@ RemyLebeau-TeamB Nút cổ chai chính của 'AnsiStartsStr' không phải là sử dụng 'copy' nội bộ, nhưng sử dụng' AnsiSameStr' gọi API Windows CompareString' rất chậm. Thực tế, hầu hết các chức năng 'Ansi *' đều gọi các API đó và chậm nếu toàn bộ xử lý Unicode không cần thiết (ví dụ: khi sử dụng các ký tự 7 bit Ascii, điều này xảy ra rất nhiều trong lập trình). Toàn bộ RTL có đầy đủ mã làm việc, nhưng không được viết cho tốc độ. Yêu thích của tôi là 'IntToStr' thực hiện mà chỉ là damn chậm (thậm chí chậm hơn kể từ Delphi 2009). –

4

Nếu bạn cần tốc độ với sự linh hoạt bạn có thể thử một cái gì đó như:

function StatsWith(const SubStr, Str: string): Boolean; inline; 
begin 
    if Length(SubStr) <= Length(Str) then 
    Result := CompareMem(Pointer(SubStr), Pointer(Str), ByteLength(SubStr)) 
    else 
    Result := False; 
end; 
+0

ByteLength() sẽ hoạt động với Delphi 2009+ mà tôi nghi ngờ. 'length (SubStr) * sizeof (char)' là tiêu chuẩn hơn. –

+1

@ArnaudBouchez Nếu bạn không có ý định hỗ trợ các phiên bản trình biên dịch cũ, thì 'ByteLength' là rõ ràng hơn. –

+0

ByteLength được thực hiện (trong D2010) như là một hàm nội tuyến được thực hiện như 'Length (s) * SizeOf (Char)' ... Dù sao, có thể là quá mức cần thiết, nhưng tôi có thể đi với 'Length (s) * StringElementSize (s) '. –

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