Bài đăng blog này giới thiệu cho bạn thế giới của tối ưu hóa mã, cung cấp các chiến lược thực tế để nâng cao hiệu suất mã của bạn. Chúng ta sẽ khám phá cách chọn cấu trúc dữ liệu phù hợp cho nhiệm vụ, giảm thiểu các vòng lặp và phép tính không cần thiết, tận dụng hiệu quả các kỹ thuật bộ nhớ đệm, và viết mã sạch, DRY (Don't Repeat Yourself - Đừng Lặp Lại Chính Mình). Chúng ta cũng sẽ xem xét độ phức tạp về thời gian và không gian khi xây dựng mã của bạn.
Chọn cấu trúc dữ liệu phù hợp cho nhiệm vụ của bạn.
Ví dụ: Mảng nhanh cho việc lập chỉ mục, trong khi hash tốt hơn cho tra cứu khóa-giá trị.
# Không hiệu quả
names = ["Alice", "Bob", "Charlie"]
names.include?("Bob") # Tìm kiếm qua toàn bộ mảng
# Đã tối ưu hóa
names_set = Set.new(["Alice", "Bob", "Charlie"])
names_set.include?("Bob") # Tra cứu nhanh hơn
Giảm số lần bạn lặp qua dữ liệu.
# Không hiệu quả: Nhiều vòng lặp qua cùng một dữ liệu
numbers = [1, 2, 3, 4, 5]
sum = 0
product = 1
max = numbers[0]
min = numbers[0]
numbers.each { |n| sum += n }
numbers.each { |n| product *= n }
numbers.each { |n| max = n if n > max }
numbers.each { |n| min = n if n < min }
# Đã tối ưu hóa: Một vòng lặp duy nhất để tính toán tất cả giá trị
numbers = [1, 2, 3, 4, 5]
sum = 0
product = 1
max = numbers[0]
min = numbers[0]
numbers.each do |n|
sum += n
product *= n
max = n if n > max
min = n if n < min
end
Đừng lặp lại các phép tính không thay đổi.
Ví dụ: lưu trữ kết quả của một phép tính không thay đổi, và sau đó tái sử dụng kết quả đã lưu đó thay vì tính toán lại.
class ExpensiveCalculation
def initialize
@result = nil
end
def calculate
@result ||= perform_expensive_calculation
end
private
def perform_expensive_calculation
puts "Đang thực hiện phép tính tốn kém..."
# Mô phỏng một phép tính tốn kém
sleep(2)
42
end
end
calculation = ExpensiveCalculation.new
# Lần gọi đầu tiên, thực hiện phép tính
puts calculation.calculate # => Đang thực hiện phép tính tốn kém... 42
# Lần gọi thứ hai, sử dụng kết quả đã lưu trong bộ nhớ đệm
puts calculation.calculate # => 42
Lưu trữ kết quả của các phép toán tốn kém để tái sử dụng.
Chuỗi Fibonacci, khi được triển khai đệ quy, thường dẫn đến các phép tính dư thừa. Ví dụ, cách tiếp cận đệ quy standard tính toán cùng một số Fibonacci nhiều lần. Chúng ta có thể tránh sự không hiệu quả này bằng cách sử dụng các phương pháp thay thế như cách tiếp cận lặp hoặc đệ quy đuôi. Những kỹ thuật này cho phép chúng ta lưu trữ kết quả trung gian trong các biến, loại bỏ nhu cầu tính toán lặp lại. Nguyên tắc lưu trữ kết quả thay vì tính toán lại có thể được áp dụng cho nhiều tình huống khác để cải thiện hiệu quả của mã. Để biết thêm thông tin, hãy truy cập https://vulehuan.com/vi/blog/2024/7/giai-ma-de-quy-hieu-ro-su-ky-dieu-dang-sau-no-66951c56cdb8828661f4c41d.html
Ý tưởng bộ nhớ đệm web:
Sắp xếp các điều kiện một cách hiệu quả và sử dụng case khi thích hợp.
# Không hiệu quả
if x == 1
puts "Một"
elsif x == 2
puts "Hai"
elsif x == 3
puts "Ba"
end
# Đã tối ưu hóa
case x
when 1 then puts "Một"
when 2 then puts "Hai"
when 3 then puts "Ba"
end
Ví dụ: Ruby có nhiều phương thức tích hợp hiệu quả. Hãy sử dụng chúng!
# Không hiệu quả
words = text.split(" ")
word_count = {}
words.each do |word|
word_count[word] ||= 0
word_count[word] += 1
end
# Đã tối ưu hóa
word_count = text.split.tally
Đừng lặp lại chính mình. Hợp nhất mã lặp lại thành các hàm.
Bạn đã nghe về DRY (Don't Repeat Yourself - Đừng Lặp Lại Chính Mình) chưa? Nó tránh sự trùng lặp mã, thúc đẩy mã sạch hơn và dễ bảo trì hơn. Để biết thêm thông tin, hãy truy cập https://vulehuan.com/vi/blog/2024/7/viet-ma-sach-hon-de-bao-tri-voi-cac-nguyen-tac-dry-kiss-solid-6688d0fac9dec2dec37a1b9b.html
Suy nghĩ về cách mã của bạn mở rộng với đầu vào lớn hơn.
# Độ phức tạp thời gian O(n^2)
def has_duplicate?(array)
array.each_with_index do |item, i|
array[(i+1)..-1].each do |other|
return true if item == other
end
end
false
end
# Độ phức tạp thời gian O(n), độ phức tạp không gian O(n)
def has_duplicate?(array)
seen = Set.new
array.each do |item|
return true if seen.include?(item)
seen.add(item)
end
false
end