2010-06-09 44 views
5

Tôi đã đấu tranh với một ứng dụng tôi đang viết và tôi nghĩ rằng tôi bắt đầu thấy rằng vấn đề của tôi là tối ưu hóa sớm. Bên cầu toàn của tôi muốn làm mọi thứ tối ưu và hoàn hảo trong lần đầu tiên, nhưng tôi thấy điều này làm phức tạp thiết kế một chút. Thay vì viết các hàm nhỏ, có thể kiểm thử thực hiện một điều đơn giản, tôi đang nghiêng về việc nhồi nhét nhiều chức năng nhất có thể để có hiệu quả hơn.Tôi có hiểu chính xác tối ưu hóa sớm không?

Ví dụ: tôi tránh nhiều chuyến đi đến cơ sở dữ liệu cho cùng một phần thông tin với chi phí mã của tôi trở nên phức tạp hơn. Một phần của tôi muốn không lo lắng về các cuộc gọi cơ sở dữ liệu dư thừa. Nó sẽ làm cho nó dễ dàng hơn để viết mã chính xác và số lượng dữ liệu được lấy là nhỏ anyway. Phần khác của tôi cảm thấy rất bẩn thỉu và ô uế khi làm việc này. :-)

Tôi đang hướng tới việc chuyển sang cơ sở dữ liệu nhiều lần, điều tôi nghĩ là di chuyển đúng ở đây. Điều quan trọng hơn là tôi hoàn thành dự án và tôi cảm thấy như mình bị treo lên vì tối ưu hóa như thế này. Câu hỏi của tôi là: là chiến lược phù hợp để sử dụng khi tránh tối ưu hóa sớm?

+0

Đã có khá nhiều cuộc thảo luận về điều này trước đây: http://stackoverflow.com/search?q=premature+optimization –

+0

Nếu bạn cho chúng tôi biết ngôn ngữ và cơ sở dữ liệu bạn đang sử dụng, mọi người có thể cung cấp minh họa ví dụ. Tôi nhận ra câu hỏi của bạn là chung chung, nhưng các ví dụ thường giúp ích. – detly

+0

@detly: Đây là một ứng dụng web được hỗ trợ bởi php/mysql. –

Trả lời

20

Đây là chiến lược đúng đắn nói chung. Nhận mã hoạt động, được bao phủ kỹ lưỡng bằng các thử nghiệm tự động.

Sau đó, bạn có thể chạy các kiểm tra tự động trong khi chương trình được kiểm soát của một trình hồ sơ, để tìm ra nơi chương trình dành thời gian và/hoặc bộ nhớ. Điều đó sẽ cho bạn thấy nơi để tối ưu hóa.

Và nó sẽ cho bạn thấy cách tối ưu hóa hoạt động, không mã nào có thể hoạt động hoặc không hoạt động khi tất cả được kết hợp với nhau.

Bạn không muốn mã không thành công tối ưu.


Các quote Tôi đã thất bại trong việc ghi nhớ là từ Mich Ravera:

Nếu nó không hoạt động, nó không quan trọng nhanh như thế nào nó không hoạt động.

+12

"Bạn không muốn mã không thành công tối ưu". - cách tuyệt vời để đặt nó! –

+0

@Paperjam: một người khác đã nói điều tương tự. Tôi không thể nhớ chính xác điều gì. –

5

Chúng ta nên quên hiệu quả nhỏ, khoảng 97% thời gian: tối ưu hóa sớm là gốc rễ của mọi điều xấu xa. - Hoare

Khi @John Saunders làm móng, việc áp dụng TDD có thể không hoàn toàn giải quyết các mối quan tâm của bạn. Tôi tuân thủ TDD, và khi bạn thực hiện TDD một cách chính xác, và nếu bạn có thể áp dụng tái cấu trúc hiệu quả, bạn thường kết thúc với nhiều mã gọn gàng hơn, và với lợi ích mà bạn biết nó hoạt động. Không có đối số ở đó.

Tuy nhiên, tôi thấy quá nhiều nhà phát triển viết mã hiệu suất không biết gì - tránh tối ưu hóa sớm không có lý do gì để viết mã sloppy/lười/ngây thơ. Viết các bài kiểm tra đơn vị không ngăn chặn điều này. Mặc dù ai đó viết bài kiểm tra đơn vị có lẽ là một coder tốt hơn, và các lập trình viên tốt hơn ít có khả năng viết mã xấu thường xuyên hơn.

Làm viết kiểm tra và làm bao gồm kiểm tra hiệu suất vào bộ kiểm tra các tình huống mà các bên liên quan xác định. ví dụ.lấy 100 sản phẩm chiết khấu cho một nhà cung cấp cụ thể, và bao gồm các cấp độ thả giống và định dạng như Xml trong dưới 3 giây

Các sai lầm rằng "sớm tối ưu hóa" là điều tương tự như "lo ngại về hiệu suất" không nên hướng dẫn phần mềm phát triển. - Randall Hyde

Nếu bạn để lại mối quan tâm về hiệu suất quá trễ, bạn có thể thấy quá khó hoặc quá tốn kém để thay đổi.

Một số bài

+0

Tôi e là tôi không đồng ý một phần. Viết "điều đơn giản nhất có thể làm việc" có thể dẫn đến viết mã ngây thơ. Nhưng bằng cách sử dụng TDD, bạn sẽ nhận được độ bao phủ mã tuyệt vời - đủ để bạn có thể sử dụng các kiểm tra đó để thúc đẩy quá trình điều tra và hiệu chỉnh hoạt động. –

+0

@ John Saunders Tôi không biết bạn không đồng ý với điều gì? Câu trả lời của tôi cố gắng khuyến khích OP viết các bài kiểm tra dựa trên kỳ vọng về hiệu suất của các bên liên quan. Tôi đã viết lại để làm rõ. –

+0

Tôi có thể làm rõ bằng cách nói rằng mã của bạn phải vượt qua tất cả các bài kiểm tra - bao gồm kiểm tra hiệu suất. Tuy nhiên, một sự cân bằng hợp lý phải được thực hiện giữa nhận được mã để làm việc và nhận được mã để làm việc tốt. Mã hoạt động kém có thể cần phải được thiết kế lại để đáp ứng các mục tiêu hiệu suất. Nhưng nếu nó vượt qua tất cả các thử nghiệm tự động, thì việc thiết kế lại có thể tiến hành như là một phép tái cấu trúc, với sự tự tin lớn hơn nhiều rằng mã vẫn hoạt động. –

1

Khía cạnh quan trọng của quote Knuth với tôi là "penny-khôn ngoan và lb-ngu ngốc". Đó là cách cuối cùng ông mô tả người tối ưu hóa sớm - một người nào đó cãi nhau về việc tiết kiệm đồng xu khi có số tiền để được cứu, và đấu tranh để duy trì phần mềm "tối ưu hóa" (chú ý cẩn thận đến cách ông sử dụng trích dẫn ở đây).

Tôi tìm thấy rất nhiều người thường chỉ trích dẫn một phần nhỏ của bài báo của Knuth. Thật đáng để nhận ra bài báo của anh ta đang tranh cãi để sử dụng goto để tăng tốc đường dẫn thực thi quan trọng trong phần mềm.

Một câu nói đầy đủ hơn:

[...] đây là một tiết kiệm đáng kể trong tốc độ chạy tổng thể, nếu, chẳng hạn, giá trị trung bình của n là khoảng 20, và nếu các thói quen tìm kiếm được thực hiện khoảng một triệu lần trong chương trình. Việc tối ưu hóa vòng lặp như vậy [sử dụng gotos] không khó để tìm hiểu và, như tôi đã nói, chúng chỉ thích hợp trong một phần nhỏ của một chương trình, nhưng chúng thường tiết kiệm đáng kể. [...]

Trí tuệ thông thường được chia sẻ bởi nhiều kỹ sư phần mềm ngày nay kêu gọi bỏ qua hiệu quả trong nhỏ; nhưng tôi tin rằng điều này chỉ đơn giản là phản ứng quá mức với những hành vi lạm dụng mà họ thấy được thực hiện bởi những người lập trình penny-khôn ngoan và ngu ngốc, những người không thể gỡ lỗi hoặc duy trì các chương trình "tối ưu hóa" của họ. Trong kỹ thuật thành lập các ngành có cải thiện 12%, dễ dàng thu được, không bao giờ được coi là cận biên; và tôi tin rằng quan điểm tương tự sẽ chiếm ưu thế trong kỹ thuật phần mềm . Tất nhiên tôi sẽ không bận tâm đến việc tối ưu hóa như vậy trên một công việc oneshot, nhưng khi đó là câu hỏi về chuẩn bị các chương trình chất lượng, Tôi không muốn giới hạn bản thân mình với các công cụ từ chối hiệu quả của mình như vậy .

Không nghi ngờ gì về việc hiệu quả dẫn đến lạm dụng. Người lập trình lãng phí một lượng lớn thời gian để suy nghĩ hoặc lo lắng về các tốc độ của các phần không quan trọng trong chương trình của họ, và những nỗ lực này thực sự có tác động tiêu cực mạnh khi xem xét và sửa lỗi . Chúng ta nên quên đi hiệu suất nhỏ, nói 97% thời gian; tối ưu hóa sớm là gốc của tất cả các điều ác.

Nó thường là một sai lầm để làm cho một bản án tiên nghiệm về những phần của một chương trình là thực sự quan trọng, vì những kinh nghiệm phổ quát của lập trình viên đã được sử dụng các công cụ đo lường đã được rằng đoán trực giác của họ thất bại. Sau khi làm việc với các công cụ như vậy trong bảy năm, tôi đã tin rằng tất cả các trình biên dịch được viết từ bây giờ nên được thiết kế để cung cấp cho tất cả các lập trình viên những phản hồi cho thấy phần nào của chương trình của họ là tốn kém nhất; thực sự, phản hồi này sẽ được cung cấp tự động trừ khi nó đã được tắt một cách cụ thể.

Sau một lập trình viên biết phần nào của thói quen của mình thực sự quan trọng, việc chuyển đổi như tăng gấp đôi vòng lặp sẽ đáng giá. Lưu ý rằng chuyển đổi này giới thiệu các câu lệnh go to - và do đó thực hiện một số tối ưu hóa vòng lặp khác.

Vì vậy, đây là đến từ một người đã thực sự lo ngại sâu sắc với hiệu suất ở cấp vi mô, và vào thời điểm đó (tối ưu đã nhận được tốt hơn bây giờ), được sử dụng goto cho tốc độ.

Tại trung tâm của thành lập "tối ưu hóa non" của Knuth này là:

  1. tối ưu hóa dựa trên linh cảm/mê tín/trực giác của con người không có kinh nghiệm trong quá khứ hay đo (tối ưu hóa một cách mù quáng mà không thực sự biết những gì bạn đang làm).
  2. Tối ưu hóa theo cách tiết kiệm đồng xu trên bảng Anh (tối ưu hóa không hiệu quả).
  3. Tìm kiếm một số đỉnh cao tuyệt đối của hiệu quả cho mọi thứ.
  4. Tìm kiếm hiệu quả trong đường dẫn không quan trọng.
  5. Cố gắng tối ưu hóa khi bạn hầu như không thể duy trì/gỡ lỗi mã của mình.

Không có điều này liên quan đến thời gian tối ưu hóa của bạn, nhưng trải nghiệm và hiểu - từ việc hiểu các đường dẫn quan trọng để hiểu những gì thực sự mang lại hiệu suất.

Những điều như phát triển theo hướng kiểm tra và tập trung chủ yếu vào thiết kế giao diện không được đề cập trong bài báo của Knuth. Đây là những khái niệm và ý tưởng hiện đại hơn. Ông đã tập trung vào thực hiện chủ yếu. Tuy nhiên, đây là một cập nhật tốt cho lời khuyên của Knuth - để tìm cách thiết lập tính chính xác trước tiên thông qua thử nghiệm và thiết kế giao diện để bạn tối ưu hóa mà không phá vỡ mọi thứ.

Nếu chúng tôi cố gắng áp dụng một giải thích hiện đại về Knuth, tôi sẽ thêm "tàu" vào đó. Ngay cả khi bạn đang tối ưu hóa các đường dẫn quan trọng thực sự của phần mềm của bạn với lợi ích đo được, phần mềm nhanh nhất trên thế giới là vô giá trị nếu nó không bao giờ tàu. Việc lưu ý điều đó sẽ giúp bạn thực hiện các thỏa hiệp thông minh hơn.

Tôi đang hướng tới việc chuyển sang cơ sở dữ liệu nhiều lần, mà tôi nghĩ là di chuyển đúng ở đây. Điều quan trọng hơn là tôi hoàn thành dự án và tôi cảm thấy như tôi bị treo máy vì tối ưu hóa như thế này. Câu hỏi của tôi là: đây có phải là chiến lược phù hợp để sử dụng khi tránh tối ưu hóa sớm không?

Nó sẽ là loại tùy thuộc vào bạn để phát triển phán đoán tốt nhất, xem xét một số điểm nêu trên, khi bạn hiểu rõ nhất các yêu cầu của riêng bạn.

Một yếu tố quan trọng tôi đề nghị là nếu đây là một con đường quan trọng hiệu suất đối phó với một tải nặng, để thiết kế giao diện công cộng của bạn theo cách để lại nhiều chỗ để tối ưu hóa.

Ví dụ: không thiết kế hệ thống hạt có phụ thuộc của khách hàng cho giao diện Particle. Điều đó không có chỗ để tối ưu hóa, khi bạn chỉ có trạng thái đóng gói và thực hiện một hạt đơn để làm việc. Trong trường hợp đó, bạn có thể phải thực hiện các thay đổi tầng cho codebase của mình để tối ưu hóa. Một chiếc xe đua không thể sử dụng tốc độ của nó nếu đường chỉ dài 10 mét. Thay vào đó, thiết kế hướng tới giao diện ParticleSystem tổng hợp một triệu hạt, ví dụ: với các hoạt động cấp cao hơn xử lý các hạt hàng loạt khi có thể. Điều đó khiến bạn có nhiều không gian để tối ưu hóa mà không phá vỡ thiết kế của bạn nếu bạn thấy bạn cần tối ưu hóa.

Phía cầu toàn của tôi muốn làm tất cả mọi thứ tối ưu và hoàn hảo lần đầu tiên thông qua, nhưng tôi đang tìm kiếm này đang làm phức tạp thiết kế khá một chút.

Phần này có vẻ hơi sớm. Thông thường, thẻ đầu tiên của bạn phải hướng tới sự đơn giản. Tính đơn giản thường đi liền với nhanh chóng, nhanh hơn bạn có thể nghĩ ngay cả khi bạn đang làm một số công việc dư thừa.

Dù sao, tôi hy vọng những điểm này sẽ giúp ít nhất thêm một số điều cần xem xét.

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