cuốn sách gpt4 ai đã làm

Các lớp Java ByteBuffer/IntBuffer/ShortBuffer có nhanh không?

In lại Tác giả: Taklimakan Thời gian cập nhật: 2023-11-02 22:49:57 25 4
mua khóa gpt4 Nike

Tôi đang phát triển một ứng dụng Android (rõ ràng được viết bằng Java) và gần đây tôi đã cập nhật mã trình đọc UDP của mình. Trong cả hai phiên bản, tôi đã thiết lập một số bộ đệm và nhận được gói UDP:

byte[] buf = byte mới[10000];
ngắn [] soundData = ngắn mới [1000];
Gói DatagramPacket = DatagramPacket mới (buf, buf.length);
socket.receive(gói);

Trong phiên bản đầu tiên, tôi tập hợp dữ liệu lại từng byte một (thực tế là 16 mẩu dữ liệu âm thanh PCM):

cho (int i = 0; i < đếm; i++)
soundData[i] = (ngắn) (((buf[k++]&0xff) << 8) + (buf[k++]&0xff));

Trong các phiên bản mới hơn, tôi sử dụng một số công cụ Java thú vị mà tôi chưa biết khi bắt đầu:

bBuffer = ByteBuffer.wrap (buf);
sBuffer = bBuffer.asShortBuffer();
sBuffer.get (soundData, 0, đếm);

Trong cả hai trường hợp, "số" được điền chính xác (tôi đã kiểm tra). Tuy nhiên, dường như có một vấn đề mới xảy ra với âm thanh phát trực tuyến của tôi - có thể âm thanh phát trực tuyến của tôi không được xử lý đủ nhanh - điều này không có ý nghĩa gì đối với tôi. Rõ ràng mã bộ đệm được biên dịch thành nhiều hơn ba câu lệnh mã JVM, nhưng khi tôi bắt đầu việc này, có vẻ như giả định hợp lý rằng phiên bản thứ hai sẽ nhanh hơn phiên bản đầu tiên.

Nhìn bề ngoài, tôi không nhất quyết rằng mã của tôi phải sử dụng bộ đệm Java NIO, nhưng ít nhất thoạt nhìn, có vẻ giống như một con mo'betta' làm như vậy.

Có ai có đề xuất nào về trình đọc UDP Java đơn giản, nhanh chóng không? Có "cách tốt nhất" được chấp nhận rộng rãi để thực hiện việc này không?

谢谢,

câu trả lời hay nhất

Mã của bạn sẽ hiệu quả hơn nếu thay vì đọc gói thành một mảng byte (sao chép dữ liệu từ bộ đệm gốc vào mảng), sau đó gói nó vào một ByteBuffer mới (tạo một đối tượng mới) và chuyển đổi nó thành một ShortBuffer (tạo một đối tượng mới) Bạn chỉ đặt đối tượng một lần và tránh sao chép.

Bạn có thể thực hiện việc này bằng cách tạo socket bằng DatagramChannel.socket(), sau đó kết nối với nó như bình thường và lấy đối tượng DatagramChannel bằng socket.getChannel(). Đối tượng này sẽ cho phép bạn đọc các gói trực tiếp vào ByteBuffer hiện có (bạn nên tạo gói này bằng cách sử dụng ByteBuffer.allocateDirect để có hiệu quả tối đa). Sau đó, bạn chỉ cần sử dụng asShortBuffer() một lần để tạo dữ liệu của mình dưới dạng quần short và đọc từ ShortBuffer đó sau mỗi lần nạp lại ByteBuffer.

Vì vậy, mã trông như thế này:

 Ổ cắm DatagramSocket = DatagramChannel.socket();
// code kết nối socket
Kênh DatagramChannel = socket.getChannel();
Bộ đệm ByteBuffer = ByteBuffer.allocateDirect (10000);
// bạn có thể muốn gọi buffer.order(...) ở đây để cho nó biết thứ tự byte nào sẽ được sử dụng
ShortBuffer shortBuf = buffer.asShortBuffer();

// trong vòng nhận của bạn:
đệm.clear();
kênh.receive (bộ đệm);
shortBuf.position(0).limit(buffer.position()/2); // có thể bỏ qua một byte nếu nhận được số lẻ
shortBuf.get(soundBuf,0,shortBuf.limit());

Bạn sẽ thấy mã này hiệu quả hơn mã trước đó vì nó tránh được bản sao hoàn chỉnh của dữ liệu và việc chuyển đổi định dạng được xử lý bằng mã được tối ưu hóa bằng tay thay vì bằng các thao tác byte do trình biên dịch tạo ra, điều này có thể không tối ưu. Sẽ hiệu quả hơn nếu bạn sử dụng thứ tự byte gốc của nền tảng (tôi tin rằng Android sử dụng ít endian trên tất cả các nền tảng có sẵn và mã của bạn ở trên dường như là big endian, vì vậy điều này có thể không thực hiện được (đối với bạn), trong trường hợp đó là shortBuf .get() trở thành bản sao bộ nhớ trực tiếp.

Giới thiệu về java - Các lớp Java ByteBuffer/IntBuffer/ShortBuffer có nhanh không? , chúng tôi đã tìm thấy một câu hỏi tương tự trên Stack Overflow: https://stackoverflow.com/questions/4037851/

25 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress