Эффективные ведра Kademlia

Я пишу здесь модифицированную систему Kademlia P2P, но проблема, которую я здесь описываю, очень похожа на реализацию оригинальной.

Итак, каков наиболее эффективный способ реализации k-Buckets? Для меня важны время доступа, параллелизм (чтение и запись) и потребление памяти.

Думал делать это с ConcurrentLinkedQueue и ConcurrentHashMap, но это довольно избыточно и противно, не так ли?

На данный момент я просто синхронизирую LinkedList.

Вот мой код:

import java.util.LinkedList;

class Bucket {
    private final LinkedList<Neighbour> neighbours;
    private final Object lock;

    Bucket() {
        neighbours = new LinkedList<>();
        lock = new Object();
    }

    void sync(Neighbour n) {
        synchronized(lock) {
            int index = neighbours.indexOf(n);
            if(index == -1) {
                neighbours.add(n);
                n.updateLastSeen();
            } else {
                Neighbour old = neighbours.remove(index);
                neighbours.add(old);
                old.updateLastSeen();
            }
        }
    }

    void remove(Neighbour n) {
        synchronized(lock) {
            neighbours.remove(n);
        }
    }

    Neighbour resolve(Node n) throws ResolveException {
        Neighbour nextHop;
        synchronized(lock) {
            int index = neighbours.indexOf(n);
            if(index == -1) {
                nextHop = neighbours.poll();
                neighbours.add(nextHop);
                return nextHop;
            } else {
                return neighbours.get(index);
            }
        }
    }
}

Пожалуйста, не удивляйтесь, я реализовал еще один процесс выселения соседей.


person Marcel    schedule 25.10.2014    source источник


Ответы (1)


Итак, каков наиболее эффективный способ реализации k-Buckets?

Это зависит от. Если вы хотите сделать реализацию с прибамбасами (например, разделение ведра, множественная адресация), вам нужен гибкий список или дерево. По моему опыту, копирование массива записи + бинарный поиск хорошо работает для таблицы маршрутизации, потому что вы редко изменяете общее количество сегментов, а только содержимое сегментов.

С семантикой CoW вам нужно меньше блокировок, поскольку вы можете просто получить текущую копию массива, получить интересующую корзину, а затем заблокировать ее. Или используйте атомарный массив внутри каждого ведра. Но, конечно, такие оптимизации необходимы только в том случае, если вы ожидаете высокую пропускную способность, большинство узлов DHT видят очень небольшой трафик, максимум несколько пакетов в секунду, то есть нет необходимости задействовать несколько потоков, если только вы не реализуете специализированный узел с такой большой пропускной способностью, что для обработки данных требуется несколько потоков.

CoW работает хуже для кэшей поиска, подобных таблицам маршрутизации, или эфемерных наборов посещенных/целевых узлов, созданных во время поиска, поскольку они быстро изменяются. ConcurrentSkipListMaps может быть лучшим выбором, если вы ожидаете высокую нагрузку.

Если вам нужна упрощенная приблизительная реализация, просто используйте массив фиксированного размера из 160 элементов, где индекс массива – это число битов общего префикса относительно идентификатора вашего узла. . Это работает достаточно хорошо, но не позволяет использовать некоторые оптимизации, предложенные в полном документе kademlia.

person the8472    schedule 18.12.2014