[英]Why is my modulus-based buffer slower than a LinkedList for writing?
背景:
我試圖找到最快的(關於寫入速度)鍵值存儲來支持我擁有的應用程序。 存儲的最大容量為15,000個鍵值對。 我嘗試了以下方法:
LinkedHashMap
,重寫removeEldestEntry可以在地圖中的項目數達到15000時刪除最舊的條目:
new LinkedHashMap<Long, Object>(10000, 0.75F, false) { private static final long serialVersionUID = 1L; protected boolean removeEldestEntry(Map.Entry<Long, Object> eldest) { return size() > 15000; } };
LinkedList
,如果大小已經達到最大值,則刪除第一個元素(要獲取具有鍵id
元素,將按順序搜索列表):
new LinkedList<Object>() { private static final long serialVersionUID = 1L; public boolean add(Object o) { while (size() >= 15000) remove(0); return super.add(o); } };
我可以想到的ModBuffer
,這是我能想到的(理論上)最快的存儲(如列表中,找到具有鍵id
元素,整個緩沖區將按順序搜索):
public class ModBuffer<T> { private T[] buffer = (T[]) new Object[15000]; public add(Long key, T value) { int pos = (int) (key % (long) buffer.length); buffer[pos] = value; }
直觀地看,ModBuffer似乎是編寫速度最快的一種。 但是事實證明,LinkedList是最快的。 我正在使用這些緩沖區來實現網絡協議。 有了LinkedList,我設法達到850Mbps。 使用ModBuffer,它不會超過700Mbps。
題:
為什么LinkedList的編寫速度比簡單的ModBuffer快得多? 由於它是標准Java Collections的一部分,它是否以某種方式進行了優化? 我想不出任何其他原因了……這很有趣。
我懷疑是模運算符比添加到鏈表中要慢。 在ModBuffer
實現中,始終執行模數。 另一方面, LinkedList
實現調用一個O(1)
size方法,然后調用另一個O(1)
add方法插入列表的開頭。 如果條目數不超過15k的最大值,則可以通過while
條件中的分支預測來增加一項改進:
while (size() >= 15000)
remove(0);
如果您要在循環中添加元素並且條目數未達到最大值,則大多數情況下將返回false。
但是,對於大量條目,情況並非如此-模數緩沖區應該更有效。
聽起來您在談論協議的速度,而不是高速緩存的寫入速度。 如果協議中有重傳部分,那么較低的速度可能是由於ModBuffer奇怪且可能很差的保留特性引起的。 當基於LinkedList的解決方案丟棄隊列中最舊的記錄時,ModBuffer解決方案有效地丟棄隨機記錄; 每當發生緩存沖突時,它都會丟棄記錄。 可能需要重新傳輸這些丟失的記錄,這使您放慢了速度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.