2012-06-25 18 views
10

Tôi đang cố gắng "dọn sạch" một ByteBuffer thành tất cả các byte không (tất cả 0x00). Tôi đã cố gắng lặp qua tất cả các vị trí trong bộ đệm và đặt chúng thành 0x00, nhưng hiệu quả là xấu. Có cách nào tốt hơn để nhanh chóng xóa một ByteBuffer - tương tự như những gì BitSet.clear() không?Xóa nhanh (không rõ) một ByteBuffer trong Java

Xin lưu ý rằng ByteBuffer.clear() không phải là giải pháp thích hợp cho tôi trong trường hợp này - tôi phải xóa tất cả dữ liệu bên trong bộ đệm và không chỉ đặt lại con trỏ về đầu.

Bất kỳ gợi ý nào?

Chỉnh sửa: ByteBuffer được sử dụng như một phần của bảng băm và nó duy trì các tham chiếu của các mục bảng băm. Mỗi khi bảng băm cần được xóa, tôi phải thiết lập lại các mục bảng băm để chèn bảng băm sau này. Kể từ khi bảng băm được truy cập một cách ngẫu nhiên, tôi không thể chỉ rõ ràng() trạng thái của bộ đệm byte.

+0

Bạn có thể giải thích trường hợp sử dụng một cách chi tiết hơn không? Bạn nhận được cái gì? – jontro

+0

Tại sao bạn nghĩ rằng bạn cần phải không ra khỏi bộ đệm? – EJP

+0

Đây có phải là bộ đệm trực tiếp không? Nếu không, những gì về chỉ 'ByteBuffer.wrap (byte mới [123456]);' –

Trả lời

6

Bạn đã thử sử dụng một trong các phương pháp ByteBuffer.put(byte[]) hoặc ByteBuffer.put(ByteBuffer) để viết nhiều số không trong một lần? Sau đó bạn có thể lặp qua bộ đệm theo các khối 100 hoặc 1000 byte hoặc bất kỳ thứ gì, bằng cách sử dụng một mảng hoặc bộ đệm được điền sẵn với số không.

Nhược điểm: đây là một hoạt động bắt buộc, vì vậy không phải tất cả triển khai của ByteBuffer được yêu cầu phải cung cấp cho nó ...

+0

Sẽ dùng thử. Hy vọng rằng một số lượng lớn sẽ được tốt hơn so với vòng lặp ... thx! – asksw0rder

+2

Xin lỗi vì trả lời trễ này, nhưng cách tiếp cận này thực sự hoạt động trên việc giảm chi phí xả nước. Tôi đã thấy thời gian xả nước giảm từ ~ 60ms xuống ~ 2ms. Sẽ xem liệu nó là đủ tốt. – asksw0rder

4

Đối ByteBuffer triển khai cung cấp các tùy chọn array() phương pháp (nơi hasArray() lợi nhuận true), bạn có thể sử dụng này phương thức nhận tham chiếu đến mảng cơ bản, sau đó sử dụng java.util.Arrays#fill().

1

Nếu bạn cần một ByteBuffer sạch sẽ không sạch sẽ sau khi bảng băm được flushed, cách dễ nhất là để quên ByteBufefr hiện có và phân bổ một cái mới. Tài liệu chính thức không nói như vậy, nhưng tất cả các cách triển khai đã biết đều là bộ nhớ của các bộ đệm mới. Xem http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6535542 để biết thêm thông tin.

1

Như DNA đề cập, có bộ đệm được điền sẵn và sử dụng ByteBuffer.put(ByteBuffer) có lẽ là cách di động nhanh nhất. Nếu đó là không thực tế, bạn có thể làm một cái gì đó như thế này để tận dụng lợi thế của một trong hai Arrays.fill hay Unsafe.putLong khi áp dụng:

public static void fill(ByteBuffer buf, byte b) { 
    if (buf.hasArray()) { 
     final int offset = buf.arrayOffset(); 
     Arrays.fill(buf.array(), offset + buf.position(), offset + buf.limit(), b); 
     buf.position(buf.limit()); 
    } else { 
     int remaining = buf.remaining(); 
     if (UNALIGNED_ACCESS) { 
      final int i = (b << 24) | (b << 16) | (b << 8) | b; 
      final long l = ((long) i << 32) | i; 
      while (remaining >= 8) { 
       buf.putLong(l); 
       remaining -= 8; 
      } 
     } 
     while (remaining-- > 0) { 
      buf.put(b); 
     } 
    } 
} 

Thiết UNALIGNED_ACCESS đòi hỏi một số kiến ​​thức về thực hiện JRE của bạn và nền tảng. Đây là cách tôi sẽ thiết lập nó cho Oracle JRE khi sử dụng JNA (cung cấp Platform.ARCH như một cách thuận tiện, kinh điển để truy cập vào thuộc tính hệ thống os.arch).

/** 
* Indicates whether the ByteBuffer implementation likely supports unaligned 
* access of multi-byte values on the current platform. 
*/ 
private static final boolean UNALIGNED_ACCESS = Platform.ARCH.startsWith("x86"); 
Các vấn đề liên quan