Các yếu tố tạo nên độ trễ âm thanh

Trang này tập trung vào các yếu tố đóng góp vào độ trễ đầu ra, nhưng nội dung thảo luận tương tự cũng áp dụng cho độ trễ đầu vào.

Giả sử mạch tương tự không đóng góp đáng kể, thì các yếu tố chính ở cấp độ bề mặt góp phần gây ra độ trễ âm thanh là:

  • Ứng dụng
  • Tổng số vùng đệm trong quy trình
  • Kích thước của mỗi bộ đệm, tính bằng khung
  • Độ trễ bổ sung sau khi bộ xử lý ứng dụng, chẳng hạn như từ DSP

Danh sách cộng tác viên ở trên có thể chính xác nhưng cũng gây hiểu lầm. Lý do là số lượng vùng đệm và kích thước vùng đệm là hiệu ứng hơn là nguyên nhân. Thông thường, một lược đồ vùng đệm nhất định được triển khai và kiểm thử, nhưng trong quá trình kiểm thử, âm thanh bị thiếu hoặc vượt quá sẽ được nghe thấy dưới dạng "nhấp" hoặc "bật". Để bù lại, nhà thiết kế hệ thống sẽ tăng kích thước bộ đệm hoặc số lượng bộ đệm. Điều này mang lại kết quả mong muốn là loại bỏ tình trạng thiếu hoặc vượt quá, nhưng cũng có tác dụng phụ không mong muốn là làm tăng độ trễ. Để biết thêm thông tin về kích thước vùng đệm, hãy xem video Độ trễ âm thanh: kích thước vùng đệm.

Một phương pháp tốt hơn là tìm hiểu nguyên nhân của tình trạng thiếu và vượt quá, sau đó khắc phục những vấn đề đó. Điều này giúp loại bỏ các hiện tượng âm thanh và có thể cho phép vùng đệm nhỏ hơn hoặc ít hơn, nhờ đó giảm độ trễ.

Theo kinh nghiệm của chúng tôi, những nguyên nhân phổ biến nhất gây ra tình trạng thiếu và vượt quá thời lượng bao gồm:

  • Linux CFS (Trình lập lịch biểu hoàn toàn công bằng)
  • luồng có mức độ ưu tiên cao với tính năng lập lịch biểu SCHED_FIFO
  • đảo ngược mức độ ưu tiên
  • độ trễ lên lịch dài
  • trình xử lý ngắt chạy trong thời gian dài
  • thời gian tắt do gián đoạn lâu
  • quản lý nguồn
  • hạt nhân bảo mật

Lên lịch CFS và SCHED_FIFO của Linux

CFS của Linux được thiết kế để công bằng với các khối lượng công việc cạnh tranh dùng chung một tài nguyên CPU. Tính công bằng này được thể hiện bằng tham số nice trên mỗi luồng. Giá trị tốt nằm trong khoảng từ -19 (thấp nhất hoặc thời gian CPU được phân bổ nhiều nhất) đến 20 (cao nhất hoặc thời gian CPU được phân bổ ít nhất). Nhìn chung, tất cả các luồng có giá trị nice nhất định sẽ nhận được thời gian CPU gần như bằng nhau và các luồng có giá trị nice thấp hơn về mặt số học sẽ nhận được nhiều thời gian CPU hơn. Tuy nhiên, CFS chỉ "công bằng" trong khoảng thời gian quan sát tương đối dài. Trong các khoảng thời gian quan sát ngắn hạn, CFS có thể phân bổ tài nguyên CPU theo những cách không mong muốn. Ví dụ: CPU có thể chuyển từ luồng có độ tốt thấp sang luồng có độ tốt cao. Trong trường hợp âm thanh, điều này có thể dẫn đến tình trạng thiếu hoặc thừa.

Giải pháp rõ ràng là tránh CFS cho các luồng âm thanh hiệu suất cao. Kể từ Android 4.1, các luồng như vậy hiện sử dụng chính sách lên lịch SCHED_FIFO thay vì chính sách lên lịch SCHED_NORMAL (còn gọi là SCHED_OTHER) do CFS triển khai.

Mức độ ưu tiên SCHED_FIFO

Mặc dù các luồng âm thanh hiệu suất cao hiện sử dụng SCHED_FIFO, nhưng các luồng này vẫn dễ bị ảnh hưởng bởi các luồng SCHED_FIFO có mức độ ưu tiên cao hơn. Đây thường là các luồng worker của hạt nhân, nhưng cũng có thể có một vài luồng người dùng không phải âm thanh có chính sách SCHED_FIFO. Các mức độ ưu tiên SCHED_FIFO có sẵn dao động từ 1 đến 99. Các luồng âm thanh chạy ở mức độ ưu tiên 2 hoặc 3. Điều này giúp mức độ ưu tiên 1 dành cho các luồng có mức độ ưu tiên thấp hơn và mức độ ưu tiên từ 4 đến 99 dành cho các luồng có mức độ ưu tiên cao hơn. Bạn nên sử dụng mức độ ưu tiên 1 bất cứ khi nào có thể và dành mức độ ưu tiên từ 4 đến 99 cho các luồng được đảm bảo hoàn tất trong một khoảng thời gian giới hạn, thực thi với khoảng thời gian ngắn hơn khoảng thời gian của luồng âm thanh và được biết là không gây cản trở việc lên lịch cho luồng âm thanh.

Lên lịch theo tốc độ một chiều

Để biết thêm thông tin về lý thuyết chỉ định mức độ ưu tiên cố định, hãy xem bài viết trên Wikipedia về Lên lịch theo tốc độ tuần tự (RMS). Điểm chính là bạn phải phân bổ mức độ ưu tiên cố định một cách nghiêm ngặt dựa trên khoảng thời gian, trong đó mức độ ưu tiên cao hơn được chỉ định cho các luồng có khoảng thời gian ngắn hơn, chứ không phải dựa trên "tầm quan trọng" được nhận thấy. Các luồng không định kỳ có thể được mô hình hoá dưới dạng luồng định kỳ, sử dụng tần suất thực thi tối đa và phép tính tối đa cho mỗi lần thực thi. Nếu không thể mô hình hoá luồng không định kỳ dưới dạng luồng định kỳ (ví dụ: luồng có thể thực thi với tần suất không giới hạn hoặc phép tính không giới hạn cho mỗi lần thực thi), thì bạn không nên chỉ định mức độ ưu tiên cố định cho luồng đó vì điều đó sẽ không tương thích với việc lên lịch của các luồng định kỳ thực sự.

Đảo ngược mức độ ưu tiên

Đảo ngược mức độ ưu tiên là một lỗi điển hình của các hệ thống thời gian thực, trong đó một tác vụ có mức độ ưu tiên cao hơn bị chặn trong một khoảng thời gian không giới hạn để chờ một tác vụ có mức độ ưu tiên thấp hơn giải phóng tài nguyên, chẳng hạn như (trạng thái dùng chung được bảo vệ bằng) một mutex. Hãy xem bài viết "Tránh đảo ngược mức độ ưu tiên" để biết các kỹ thuật giúp giảm thiểu vấn đề này.

Độ trễ khi lên lịch

Độ trễ lên lịch là khoảng thời gian từ khi một luồng sẵn sàng chạy đến khi quá trình chuyển đổi ngữ cảnh kết thúc để luồng đó thực sự chạy trên CPU. Độ trễ càng ngắn càng tốt và mọi độ trễ trên 2 mili giây đều gây ra vấn đề cho âm thanh. Độ trễ lập lịch biểu dài có nhiều khả năng xảy ra trong quá trình chuyển đổi chế độ, chẳng hạn như khởi động hoặc tắt CPU, chuyển đổi giữa hạt nhân bảo mật và hạt nhân thông thường, chuyển từ chế độ nguồn điện đầy đủ sang chế độ nguồn điện thấp hoặc điều chỉnh tần số xung nhịp và điện áp của CPU.

Gián đoạn

Trong nhiều thiết kế, CPU 0 sẽ xử lý tất cả các ngắt bên ngoài. Vì vậy, trình xử lý ngắt chạy trong thời gian dài có thể trì hoãn các ngắt khác, đặc biệt là ngắt hoàn tất truy cập bộ nhớ trực tiếp âm thanh (DMA). Thiết kế trình xử lý ngắt để hoàn tất nhanh chóng và trì hoãn công việc dài hạn cho một luồng (tốt nhất là luồng CFS hoặc luồng SCHED_FIFO có mức độ ưu tiên 1).

Tương tự, việc tắt các ngắt trên CPU 0 trong một thời gian dài cũng sẽ làm chậm quá trình xử lý các ngắt âm thanh. Thời gian tắt ngắt dài thường xảy ra trong khi chờ khoá vòng quay của hạt nhân. Xem lại các khoá vòng quay này để đảm bảo chúng được giới hạn.

Quản lý năng lượng, hiệu suất và nhiệt

Quản lý nguồn điện là một thuật ngữ rộng bao gồm các nỗ lực theo dõi và giảm mức tiêu thụ điện năng trong khi tối ưu hoá hiệu suất. Quản lý nhiệtlàm mát máy tính tương tự nhau nhưng nhằm đo lường và kiểm soát nhiệt để tránh hư hỏng do nhiệt dư thừa. Trong nhân Linux, trình quản lý CPU chịu trách nhiệm về chính sách cấp thấp, trong khi chế độ người dùng định cấu hình chính sách cấp cao. Các kỹ thuật được sử dụng bao gồm:

  • điều chỉnh điện áp động
  • điều chỉnh tần suất động
  • bật nhân động
  • chuyển đổi cụm
  • kiểm soát nguồn
  • hotplug (hotswap)
  • nhiều chế độ ngủ (dừng, dừng, rảnh, tạm ngưng, v.v.)
  • di chuyển quy trình
  • đối tượng chung sở thích của bộ xử lý

Một số thao tác quản lý có thể dẫn đến "tạm dừng công việc" hoặc thời điểm mà bộ xử lý ứng dụng không thực hiện công việc hữu ích nào. Những lần dừng công việc này có thể gây ảnh hưởng đến âm thanh, vì vậy, bạn nên thiết kế tính năng quản lý để có thể chấp nhận được trường hợp dừng công việc trong trường hợp xấu nhất khi âm thanh đang hoạt động. Tất nhiên, khi sắp xảy ra hiện tượng tăng nhiệt, việc tránh thiệt hại vĩnh viễn quan trọng hơn âm thanh!

Hạt nhân bảo mật

Hạt nhân bảo mật cho Quản lý quyền kỹ thuật số (DRM) có thể chạy trên cùng một(các) nhân xử lý ứng dụng như các nhân được dùng cho hạt nhân hệ điều hành chính và mã ứng dụng. Bất cứ thời điểm nào trong khi một hoạt động hạt nhân bảo mật đang hoạt động trên một lõi đều là thời điểm dừng hoạt động thông thường thường chạy trên lõi đó. Cụ thể, điều này có thể bao gồm cả công việc âm thanh. Theo bản chất, hành vi nội bộ của hạt nhân bảo mật là không thể hiểu được từ các lớp cấp cao hơn, do đó, mọi bất thường về hiệu suất do hạt nhân bảo mật gây ra đều đặc biệt nguy hiểm. Ví dụ: các hoạt động của hạt nhân bảo mật thường không xuất hiện trong dấu vết chuyển đổi ngữ cảnh. Chúng tôi gọi thời gian này là "thời gian tối" — thời gian trôi qua nhưng không thể quan sát được. Hạt nhân bảo mật phải được thiết kế để có thể chấp nhận trường hợp xấu nhất là ngừng hoạt động trong khi âm thanh đang hoạt động.