2014-09-01 3 views
1

Я пытаюсь понять кеш объектов Neo4j, изучив его. Мое первое впечатление от кеша объектов происходит из слайдов по этой ссылке: http://www.slideshare.net/thobe/an-overview-of-neo4j-internalsПонимание кэша объектов Neo4j

В частности, объект Node/Relationship в кеше должен выглядеть как слайд 9 или 15/42. Чтобы убедиться в этом, я написал простой серверный скрипт, используя существующее содержимое базы графиков. То, как я это делаю, пытается заглянуть в начальный виртуальный адрес объекта node/relationship, используя sun.misc.Unsafe. Программа для получения виртуального адреса является по следующей ссылке: How can I get the memory location of a object in java?

public static long addressOf(Object o) throws Exception { 
    Object[] array = new Object[] { o }; 

    long baseOffset = unsafe.arrayBaseOffset(Object[].class); 
    int addressSize = unsafe.addressSize(); 
    long objectAddress; 
    switch (addressSize) { 
    case 4: 
     objectAddress = unsafe.getInt(array, baseOffset); 
     break; 
    case 8: 
     objectAddress = unsafe.getLong(array, baseOffset); 
     break; 
    default: 
     throw new Error("unsupported address size: " + addressSize); 
    } 
    return (objectAddress); 
} 

И в сценарии Neo4j сервера (Мой главный() класс), я получаю адрес узла по идентификатору и распечатать адрес следующим образом :

void checkAddr(){ 
    nodeAddr(0); 
    nodeAddr(1); 
    nodeAddr(2); 
} 

void nodeAddr(int n){ 
    Node oneNode = graphDb.getNodeById(n); 
    Node[] array1 = {oneNode}; 

    try { 
     long address = UnsafeUtil.addressOf(array1); 
     System.out.println("Addess: " + address); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

Для начала я попробовал использовать Soft cache provider, который является стандартным случаем. Адреса получить распечатан для объекта узла 0, 1 и 2:

Addess: 4168500044 Addess: 4168502383 Addess: 4168502753

Таким образом, используя второй адрес - первый адрес и третий адрес - второй адрес, я точно знаю, сколько места занимает узел. В этом случае объект первого узла принимает 2339B, а второй принимает 370B.

Затем, чтобы увидеть влияние отключения кэша объектов, я делаю установку с NoCacheProvider:

setConfig (GraphDatabaseSettings.cache_type, NoCacheProvider.NAME)

Адрес получает распечатан в :

Addess: 4168488391 Addess: 4168490708 Addess: 4168491056

Смещение, рассчитанное так же, как в первом случае: объект первого узла принимает 2317B, а второй занимает 348B.

вот моя проблема:

  1. Поскольку я использую тот же график, и делать только для чтения запросов, почему размер одного и того же объекта узла меняется?

  2. Когда я отключил кеш объектов, почему смещение адреса выглядит так же, как если существует кеш объекта? Например, в файле хранилища узлов один узел занимает 9 байтов, что не так в моем эксперименте. Если способ получения узлового объекта проблематичен, как я могу получить виртуальный адрес правильно? И можно ли каким-либо образом узнать, где находится файл узла mmap в памяти?

  3. Как я точно знаю, что хранится в объекте-узле. Когда я посмотрел на Node.class по этой ссылке: https://github.com/neo4j/neo4j/blob/1.9.8/community/kernel/src/main/java/org/neo4j/graphdb/Node.java Не похоже, что объект узла должен выглядеть так же, как и в слайдах презентации.Скорее всего, это группа функций, используемых узловым объектом. Кроме того, это объект узла, который сразу же попадает в память как в случае без-объекта-кеша, так и в случае с объектом-кешем?

ответ

2

Объект Node не то, что Neo4j сохраняет в «кэше объектов», так что вы не собираетесь, чтобы получить намного больше информации в кэширование Neo4j, глядя на этих случаях. Реализации Node, которые дает вам Neo4j, являются экземплярами класса с именем NodeProxy и являются настолько малыми, какими они могут быть (два поля: внутренний идентификатор и ссылка на базу данных). Они просто служат вашим дескриптором узла для выполнения операций вокруг этого узла в базе данных. Объекты, хранящиеся в «кеше объектов», являются экземплярами класса с именем NodeImpl (и, несмотря на то, что они не реализуют интерфейс Node). Объекты NodeImpl имеют форму, обозначенную на 15-м слайде (с номером страницы 9 в слайде) в этой презентации. Ну, это примерно такая форма, Neo4j развился с тех пор, как я сделал эти слайды.

Neo4j evolutioning также изменило количество байтов, которые занимают записи на диске. Neo4j 2.0 и более поздние версии имеют несколько большие записи узлов, чем те, что присутствуют в этих слайдах. Если вам интересно взглянуть на макет этих записей, вы должны посмотреть на класс NodeRecord, а затем начать с класса NodeStore и «вниз» в его зависимости, чтобы найти отображение памяти.

Помимо поиска неправильного объекта для просмотра разницы между различными подходами к кешу в Neo4j, ваш подход измерения является ошибочным. Сравнение адресов объектов ничего не говорит о размерах этих объектов. JVM не гарантирует, что два объекта, выделенные один за другим (по времени), будут располагаться рядом друг с другом в памяти, и даже если JVM использует такую ​​политику распределения, Neo4j может выделить несколько объектов между выделениями двух объектов, которые вы сравниваются. Тогда есть сборщик мусора, который мог бы перемещать объекты вокруг между вами, получая адрес одного объекта, и вы получаете адрес следующего объекта. Таким образом, просмотр адресов объектов в Java практически никогда не бывает полезен ни для чего. Для лучшего подхода при измерении размера объекта в Java просмотрите Java Object Layout utility или используйте Instrumentation.getObjectSize(...) method от агента Java.

ответить вам вопросы, как указано:

  1. Размеры объектов узла не изменяются, их адреса не гарантируется быть одинаковым между запусками. В соответствии с моим описанием выше вы не можете полагаться на адрес объекта, чтобы вычислить размер объекта.

  2. Поскольку вы смотрите на объекты NodeProxy, они будут выглядеть одинаково независимо от того, какую стратегию кеширования использует Neo4j. Чтобы взглянуть на объекты NodeImpl, вам нужно глубоко углубиться в внутренние части Neo4j. Поскольку похоже, что вы используете Neo4j 1.9, вы должны использовать экземпляр GraphDatabaseService, который у вас должен быть GraphDatabaseAPI (интерфейс, который является внутренним для реализации), затем вызовите метод getNodeManager() для этого объекта. от NodeManager вы можете позвонить по телефону getNodeIfCached(node.getId()), чтобы получить объект NodeImpl. Обратите внимание, что этот API не будет совместим между версиями Neo4j, и использование его является одной из тех ситуаций, в которых «гарантия не действует, если печать сломана» ...

  3. Посмотрите на исходный код для NodeImpl. Что касается того, когда и как данные вводятся в кеш, Neo4j пытается лениться об этом, загружая только данные, которые вы используете. Если вы получаете отношения узла, они будут загружены в кеш, и если вы получаете свойства, они будут загружены в кеш.Если вы получите только отношения, свойства никогда не будут загружены и наоборот.

Смежные вопросы