2013-10-11 15 views
10

Tôi đang phát triển trình tải xuống dựa trên Java cho dữ liệu nhị phân. Dữ liệu này được truyền qua giao thức dựa trên văn bản (mã hóa UU). Đối với tác vụ nối mạng, thư viện netty được sử dụng. Dữ liệu nhị phân được phân chia bởi máy chủ thành nhiều nghìn gói nhỏ và được gửi tới máy khách (ví dụ: ứng dụng Java).Java: Thay thế nhanh hơn cho chuỗi (byte [])

Từ netty Tôi nhận được đối tượng ChannelBuffer mỗi lần nhận được một tin nhắn mới (dữ liệu). Bây giờ tôi cần xử lý dữ liệu đó, bên cạnh các nhiệm vụ khác, tôi cần kiểm tra tiêu đề của gói đến từ máy chủ (như dòng trạng thái HTTP). Để làm như vậy, tôi gọi ChannelBuffer.array() để nhận mảng byte[]. Mảng này sau đó tôi có thể chuyển đổi thành một chuỗi thông qua new String(byte[]) và dễ dàng kiểm tra (ví dụ: so sánh) nội dung của nó (một lần nữa, như so sánh với thông báo trạng thái "200" trong HTTP).

Phần mềm tôi đang viết đang sử dụng nhiều luồng/kết nối, để tôi nhận nhiều gói từ netty song song. Tuy nhiên, điều này thường hoạt động tốt, tuy nhiên, trong khi lược tả ứng dụng tôi nhận thấy rằng khi kết nối với máy chủ tốt và dữ liệu đến rất nhanh, thì chuyển đổi này thành đối tượng String có vẻ là một nút cổ chai. Việc sử dụng CPU là gần 100% trong các trường hợp như vậy, và theo profiler rất nhiều thời gian được chi tiêu trong việc gọi hàm xây dựng String(byte[]) này.

Tôi đã tìm kiếm một cách tốt hơn để lấy từ số ChannelBuffer đến số String và nhận thấy phương thức cũ cũng có phương thức toString(). Tuy nhiên, phương pháp đó thậm chí còn chậm hơn so với phương thức khởi tạo String(byte[]).

Vì vậy, câu hỏi của tôi là: Có ai trong các bạn biết một lựa chọn tốt hơn để đạt được những gì tôi đang làm không?

+0

Tại sao? Chỉ cần gửi các byte, càng nhanh càng tốt. Quên mã uuencoding; quên việc chia tách. TCP đã không tách, và nó biết nhiều hơn về kích thước gói tối ưu trên kết nối hiện tại hơn bạn. – EJP

Trả lời

13

Có lẽ bạn có thể bỏ qua hoàn toàn chuyển đổi Chuỗi? Bạn có thể có hằng số giữ mảng byte cho các giá trị so sánh của bạn và kiểm tra mảng-to-mảng thay vì String-to-String.

Dưới đây là một số mã nhanh để minh họa. Hiện nay bạn đang làm một cái gì đó như thế này:

String http200 = "200"; 
// byte[] -> String conversion happens every time 
String input = new String(ChannelBuffer.array()); 
return input.equals(http200); 

Có lẽ đây là nhanh hơn:

// Ideally only convert String->byte[] once. Store these 
// arrays somewhere and look them up instead of recalculating. 
final byte[] http200 = "200".getBytes("UTF-8"); // Select the correct charset! 
// Input doesn't have to be converted! 
byte[] input = ChannelBuffer.array(); 
return Arrays.equals(input, http200); 
+1

+1 Tạo chuỗi có thể đắt hơn bạn mong đợi. Tránh tạo chúng và bạn có thể cải thiện hiệu suất đáng kể. –

+0

Đó là một câu trả lời tuyệt vời, cảm ơn bạn rất nhiều! – Matthias

1

Một số kiểm tra bạn đang làm chỉ có thể nhìn vào một phần của bộ đệm. Nếu bạn có thể sử dụng hình thức thay thế của hàm tạo String:

new String(byteArray, startCol, length) 

Điều đó có nghĩa là ít hơn nhiều byte được chuyển đổi thành chuỗi.

Ví dụ về tìm kiếm "200" trong thư sẽ là ví dụ.

Bạn có thể thấy rằng bạn có thể sử dụng theo chiều dài của mảng byte như một đầu mối. Nếu một số tin nhắn dài và bạn đang tìm kiếm một tin nhắn ngắn, bỏ qua những cái dài và không chuyển đổi thành ký tự. Hay đại loại thế.

Cùng với những gì @EricGrunzke nói, một phần tìm kiếm trong bộ đệm byte để lọc ra một số thông điệp và thấy rằng bạn không cần phải chuyển đổi chúng từ byte sang các ký tự.

Nếu byte của bạn là các ký tự ASCII, việc chuyển đổi sang các ký tự có thể nhanh hơn nếu bạn sử dụng charset "ASCII" thay vì bất cứ điều gì mặc định là dành cho máy chủ của bạn:

new String(bytes, "ASCII") 

sức nhanh hơn trong trường hợp đó.

Thực tế, bạn có thể chọn và chọn bộ ký tự cho ký tự byte chuyển đổi trong một số kiểu được sắp xếp để tăng tốc độ.

0

Tùy thuộc vào những gì bạn đang cố gắng làm có một vài lựa chọn:

  1. Nếu bạn đang cố gắng để có được tình trạng phản ứng để sau đó có thể không phải bạn chỉ cần gọi getStatus()? Điều này có lẽ sẽ nhanh hơn nhận được chuỗi.
  2. Nếu bạn đang cố gắng chuyển đổi bộ đệm, giả sử bạn biết nó sẽ là ASCII, nó giống như bạn làm, sau đó chỉ để lại dữ liệu dưới dạng byte [] và chuyển đổi phương thức UUDecode của bạn thành một byte [] thay vì một chuỗi.

Chi phí lớn nhất của chuyển đổi chuỗi có nhiều khả năng là sao chép dữ liệu từ mảng byte sang mảng char nội bộ của chuỗi, kết hợp với chuyển đổi này rất có thể chỉ là một loạt công việc mà bạn không không cần phải làm.

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