Có nên kiểm tra độ phức tạp thuật toán? Nếu vậy thì thế nào?


14

Giả sử tôi đang thực hiện một cái gì đó đơn giản như tìm kiếm một danh sách / mảng được sắp xếp. Hàm (trong c #) sẽ trông giống như:

static int FindIndex(int[] sortedList, int i);

Tôi có thể thực hiện và kiểm tra điều này về chức năng, nhưng vì lý do rõ ràng, tôi thường thích tìm kiếm nhị phân hơn tìm kiếm tuyến tính hoặc một cái gì đó cố ý ngu ngốc.

Vì vậy, câu hỏi của tôi là: Chúng ta có nên cố gắng viết các bài kiểm tra đảm bảo hiệu suất về độ phức tạp thuật toán không và nếu có thì bằng cách nào?

Tôi đã bắt đầu đưa ra lập luận ở cả hai phía của phần "bạn nên" trong câu hỏi này, nhưng tôi muốn xem mọi người nói gì mà không cần lập luận của tôi để nhắc họ.

Về mặt "làm thế nào", điều đó trở nên rất thú vị :) Bạn có thể thấy tham số hóa toán tử so sánh và có một bài kiểm tra mà toán tử so sánh đếm các phép so sánh hoặc đại loại như thế. Nhưng chỉ vì bạn không có nghĩa là bạn nên ...

Có ai khác đã xem xét điều này (có lẽ)? Cảm ơn.


@ steenhulthin - Tôi sẽ để máy này ở đây và kiểm tra xem. Tôi chưa từng đến đó.
SirPentor

btw, câu hỏi hay. +1
Rafael Colucci

Câu trả lời:


13

Độ phức tạp thuật toán là một cấu trúc lý thuyết và do đó, nó được "thử nghiệm" tốt nhất bằng bút chì và giấy. Nó không thể được kiểm tra một cách hữu ích về mặt cơ học.

Hiệu suất tuyệt đối có thể được kiểm tra cơ học và có thể thực hiện các bài kiểm tra đơn vị hữu ích. Nếu hiệu suất có vấn đề, thì bạn có thể chỉ định ngưỡng: "truy vấn này sẽ mất không quá 50ms để chạy trên 10 6 số và không quá 60ms trên 10 7 số." Rằng bạn có thể xây dựng một bài kiểm tra đơn vị cho.

Người dùng cuối không quan tâm thuật toán của bạn là tuyến tính hay logarit; họ quan tâm liệu UI của họ có phản hồi ngay lập tức ngay cả khi họ có dữ liệu trong một năm trong ứng dụng hay không.


Đây là bản năng của tôi là tốt. Nhưng điều khiến tôi suy nghĩ về nó là khi những người đảm bảo hiệu suất trên các khung. Ví dụ: nếu tôi nhớ lại một cách chính xác, stl có một số bò tót xung quanh độ phức tạp thuật toán (có thể tắt ở đây).
SirPentor

Chỉ vì một thư viện cung cấp một số đảm bảo không có nghĩa là chúng phải được kiểm tra đơn vị.
Svick

@Tobias Brick: Kiểm tra một cái gì đó và xác định một cái gì đó là hai điều khác nhau.
DeadMG

Chứng minh hiệu suất là khó khăn. Nó liên quan đến rất nhiều điểm mẫu cho các thông số khác nhau. Sẽ dễ dàng hơn khi các chức năng riêng lẻ không đáng kể, nhưng hơn thế nữa ... Tải của bạn, RAM, tốc độ bus trước, CPU, số lõi, mức độ xâm lấn của trình biên dịch, mức độ ô nhiễm của registry sẽ ảnh hưởng đến thời gian chạy cụ thể mẫu vật.
Công việc

3

Mặc dù tôi không chắc công cụ này có đặc biệt hữu ích cho các bài kiểm tra đơn vị hay không, bài báo "Độ phức tạp tính toán theo kinh nghiệm" của Goldsmith, Aiken và Wilkerson mô tả một phương pháp để mã hóa và quan sát hành vi động của nó trên một tập hợp các đầu vào khác nhau theo kinh nghiệm rút ra sự phức tạp tiệm cận của nó. Chương trình được mô tả trong bài báo là nguồn mở và có sẵn ở đây .

Hi vọng điêu nay co ich!


0

Điều chính là thử nó với dữ liệu lớn và xem nếu nó mất quá nhiều thời gian.

Theo kinh nghiệm điều chỉnh hiệu suất của tôi, như trong ví dụ này , điều xảy ra là nếu một số thuật toán là (ví dụ) O (n ^ 2), nó có thể sẽ ổn miễn là phần trăm thời gian nó không bao giờ được đưa lên radar.

Tuy nhiên, khi nó được cung cấp một tập dữ liệu có kích thước có thể không nhìn thấy nhưng mỗi năm một lần, phần tổng thời gian bị hút bởi thuật toán đó có thể trở nên chiếm ưu thế thảm khốc.

Nếu bạn có thể làm điều đó xảy ra trong thử nghiệm, đó là một điều rất tốt, bởi vì nó cực kỳ dễ tìm ra vấn đề, giống như đó là một vòng lặp vô hạn thực sự.


0

Tôi không nghĩ những gì bạn muốn làm là Kiểm tra đơn vị.

AFAIK, kiểm tra đơn vị chỉ để đảm bảo mã thực hiện những gì cần làm và nó không tập trung vào hiệu suất.

Từ Wikipedia : Việc kiểm tra không thể xảy ra để bắt mọi lỗi trong chương trình: không thể đánh giá mọi đường dẫn thực hiện trong tất cả các chương trình ngoại trừ các chương trình tầm thường nhất. Điều này cũng đúng với thử nghiệm đơn vị. Ngoài ra, kiểm tra đơn vị theo định nghĩa chỉ kiểm tra chức năng của chính các đơn vị. Do đó, nó sẽ không bắt lỗi tích hợp hoặc lỗi cấp hệ thống rộng hơn (chẳng hạn như các chức năng được thực hiện trên nhiều đơn vị hoặc các khu vực kiểm tra không chức năng như hiệu suất). Kiểm thử đơn vị nên được thực hiện cùng với các hoạt động kiểm thử phần mềm khác. Giống như tất cả các hình thức kiểm thử phần mềm, kiểm thử đơn vị chỉ có thể hiển thị sự hiện diện của lỗi; họ không thể hiển thị sự vắng mặt của lỗi.

Có các loại công cụ và mẫu khác để đo hiệu suất. Một trong những điều tôi có thể nhớ bây giờ là thử nghiệm Chấp nhận tập trung vào các yêu cầu phi chức năng.

Có một số khác như kiểm tra hiệu suất (sử dụng kiểm tra căng thẳng, kiểm tra tải, v.v.).

Bạn cũng có thể sử dụng một số công cụ căng thẳng cùng với một công cụ xây dựng (ant, studio xây dựng tự động) như một phần của các bước triển khai của bạn (đó là những gì tôi làm).

Vì vậy, câu trả lời ngắn gọn là không, bạn không nên lo lắng về điều đó khi đơn vị kiểm tra mã.


0

Chuyển qua bộ so sánh và theo dõi số lần nó được gọi sẽ hoạt động cho các mục đích đơn giản như kiểm tra số lượng so sánh khi thực hiện tìm kiếm trong một đầu vào cố định (giả sử new int[] { 1,2,3, ... , 1024 }) ở dưới 10. Điều đó ít nhất sẽ làm rõ ý định của bạn về cách thức hoạt động của thuật toán.

Tôi không nghĩ các bài kiểm tra đơn vị là cách phù hợp để xác minh rằng thuật toán của bạn là O (log n); điều đó sẽ cần rất nhiều việc tạo dữ liệu ngẫu nhiên, một số thống kê đường cong và có thể là thống kê sởn gai ốc để xác định xem một loạt các điểm dữ liệu có phù hợp với thời gian chạy dự kiến ​​hay không. (Đối với thuật toán này, điều này có thể thực hiện được, nhưng nếu bạn bắt đầu sắp xếp, v.v ... sẽ rất khó để lặp lại các tình huống xấu nhất).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.