Re[6]: std::map VS Dictionary.NET VS SortedDictionary.NET VS
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 08.05.12 08:53
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Потому что память пока что не бесконечная и GC требует больших затрат времени. У меня например структуры где требуется доступ по ключу, живут почти все время, что и приложение.


Так это нормально. А как ты хотел ? Удалить одно значение и освободить десять байт моментально ?

I>У тебя шота все за O(1), чтото не так с тестами. Код тестов ты не выкладывал ?


Такого плана тест. rand.bin это заархивированый фильм, источник случайной последовательности для ключей.
Тест такого плана.

int _tmain(int argc, _TCHAR* argv[])
{
    //20/21/22/23/24 /25 /26 /
    //19/14/9 /6 /3.7/2.7/2.4/
    clock_t start, finish;

    FILE* file = fopen("c:\\rand.bin", "rb");

    uint maxOffset = 0;

    keys = new uint[COUNT_KEYS];

    for(uint i=1; i<COUNT_KEYS; i++)
    {
        fread(&keys[i], 4, 1, file);
    }
    
    fclose(file);

    init(27);

    start = clock();

    for(uint i=0; i<COUNT_KEYS; i++)
    {
        insert(keys[i], keys[i]);
    }

    finish = clock();

    printf( "Filled: %2.1d msec\n", (finish - start) );

    start = clock();

    for(uint i=0; i<COUNT_KEYS; i++)
    {
        if( getValueByKey(keys[i]) != keys[i])
        {
            printf( "Error: %2.1d %2.1d\n", getValueByKey(keys[i]), keys[i]);
        }
    }
    
    finish = clock();

    delete[] keys;
    
    printf( "Searches: %2.1d msec\n", (finish - start) );
    
    uint* buff = new uint[COUNT_KEYS];

    start = clock();

    uint count = getValuesByRange(buff, COUNT_KEYS, 1, 0xFFFFFFFF);
    
    finish = clock();

    printf( "Range: %2.1d msec\n", (finish - start) );

    delete[] buff;
    
    system("pause");

    return 0;
};
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re[7]: std::map VS Dictionary.NET VS SortedDictionary.NET VS
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 08.05.12 09:03
Оценка:
Здравствуйте, PC_2, Вы писали:

I>>Потому что память пока что не бесконечная и GC требует больших затрат времени. У меня например структуры где требуется доступ по ключу, живут почти все время, что и приложение.


PC_>Так это нормально. А как ты хотел ? Удалить одно значение и освободить десять байт моментально ?


Примерно так. Есть мега-деревья, которые так и работают.

I>>У тебя шота все за O(1), чтото не так с тестами. Код тестов ты не выкладывал ?


PC_>Такого плана тест. rand.bin это заархивированый фильм, источник случайной последовательности для ключей.

PC_>Тест такого плана.

Я не понял, key это uint ? Контейнер для таких ключей я накидаю за полчаса с перерывом на обед
Re[8]: std::map VS Dictionary.NET VS SortedDictionary.NET VS
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 08.05.12 09:08
Оценка:
Здравствуйте, Ikemefula, Вы писали:

PC_>>Так это нормально. А как ты хотел ? Удалить одно значение и освободить десять байт моментально ?

I>Примерно так. Есть мега-деревья, которые так и работают.

Не, они так не работают. Читать для чего делается Shrink в СУБД.

I>Я не понял, key это uint ? Контейнер для таких ключей я накидаю за полчаса с перерывом на обед


Накидай, пока стандартные структуры сливают в разы, некоторые особо неприлично в 50+ раз.
Твоя задача сохранить 20 млн пар Int32/Int32 в структуре данных в 200 мегабайт
и обеспечить быстрый поиск по такой структуре.
Структура моделирует например телефонный справочник, где ключ номер телефона, значение указатель на имя абонента.
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re[9]: std::map VS Dictionary.NET VS SortedDictionary.NET VS
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 08.05.12 09:36
Оценка:
Здравствуйте, PC_2, Вы писали:

PC_>Твоя задача сохранить 20 млн пар Int32/Int32 в структуре данных в 200 мегабайт


Пардон, с 200 это я загнул, 400 мегабайт.
Хотя можно и в 200, только компрессионный алгоритм сьест все профиты на быстрых вставках.
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re[4]: std::map VS Dictionary.NET VS SortedDictionary.NET VS
От: Eugeny__ Украина  
Дата: 08.05.12 09:40
Оценка:
Здравствуйте, PC_2, Вы писали:


PC_>>>ап

WH>>Код где?

PC_>Код не опен сорц.

PC_>Опенсорснул я только одну из тестовых версий.
PC_>http://www.sql.ru/forum/actualfile.aspx?id=12509735

Я так понял, что ключи — всегда инты? Ну, так не интересно.
И уж тем более сравнение по скорости с универсальным Dictionary не совсем корректное.
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Re[5]: std::map VS Dictionary.NET VS SortedDictionary.NET VS
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 08.05.12 09:47
Оценка:
Здравствуйте, Eugeny__, Вы писали:

E__>Здравствуйте, PC_2, Вы писали:



PC_>>>>ап

WH>>>Код где?

PC_>>Код не опен сорц.

PC_>>Опенсорснул я только одну из тестовых версий.
PC_>>http://www.sql.ru/forum/actualfile.aspx?id=12509735

E__>Я так понял, что ключи — всегда инты? Ну, так не интересно.

E__>И уж тем более сравнение по скорости с универсальным Dictionary не совсем корректное.

Согласен маловато инта.
Но с другой стороны это краеугольный камень. Например чтобы хранить Гуиды 16 байт, можно брать первые четыре байта
а все остальное хранить списками колизий. Ну как самый простой вариант.
И получать теже 40-50 наносекунд на вставку, и 40-50 наносекунд на поиск...
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re[9]: std::map VS Dictionary.NET VS SortedDictionary.NET VS
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 08.05.12 10:24
Оценка:
Здравствуйте, PC_2, Вы писали:

PC_>Здравствуйте, Ikemefula, Вы писали:


PC_>>>Так это нормально. А как ты хотел ? Удалить одно значение и освободить десять байт моментально ?

I>>Примерно так. Есть мега-деревья, которые так и работают.

PC_>Не, они так не работают.


Работают. Как, кстати говоря, будет работать твой контейнер если ключи будут неуникальными ?

I>>Я не понял, key это uint ? Контейнер для таких ключей я накидаю за полчаса с перерывом на обед


PC_>Накидай, пока стандартные структуры сливают в разы, некоторые особо неприлично в 50+ раз.


Стандартные затачиваются под стандартные сценарии. Подо что ты заточил своё дерево — не ясно. По тем тестам и результатам ничего не ясно, где это можно использовать и какие у него свойства.

PC_>Твоя задача сохранить 20 млн пар Int32/Int32 в структуре данных в 200 мегабайт


То есть, ты предлагаешь задачу, которая сэкономит 100-200мб относительно твоей реализации ?

Покажи тест на .net, будем искать ошибку
Re[10]: std::map VS Dictionary.NET VS SortedDictionary.NET V
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 08.05.12 10:39
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Покажи тест на .net, будем искать ошибку


На преведущей странице есть с# код.
Кстате Джуди ареям я по предварительным данным, слил 50% по поиску.
Но выиграл в два раза по скорости вставок.
Таки дела.

20 тыс строк кода на Си и пацаны с Хевлет Паккарда всеже сделали свое дело
Чтож, будем думать.
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re[11]: std::map VS Dictionary.NET VS SortedDictionary.NET V
От: roro  
Дата: 08.05.12 11:51
Оценка:
Здравствуйте, PC_2, Вы писали:

PC_>Здравствуйте, Ikemefula, Вы писали:


I>>Покажи тест на .net, будем искать ошибку


PC_>На преведущей странице есть с# код.

PC_>Кстате Джуди ареям я по предварительным данным, слил 50% по поиску.
PC_>Но выиграл в два раза по скорости вставок.
PC_>Таки дела.

PC_>20 тыс строк кода на Си и пацаны с Хевлет Паккарда всеже сделали свое дело

PC_>Чтож, будем думать.

Вот тест на i5, размеро слова 64 бита, i686-apple-darwin11-llvm-gcc-4.2

word size = 8 numkeys = 1000000
generate keys
insert keys first = 1799781661ll last = 1932781528ll
insert time = 0.137306005 avg = 0.000000137 memory = 18.97 mb
read time = 0.011178000 avg = 0.000000011
range time = 0.041843001 avg = 0.000000042 items = 1000000



#include "Judy.h"

#include <stdlib.h>
#include <time.h>

#define NUMKEYS 1000000

int main(int argc,char* argv[])
{
    Pvoid_t array = NULL;
    PJError_t err = 0;

    printf("word size = %lu numkeys = %d\n",sizeof(Word_t),NUMKEYS);

    Word_t* keys = malloc(NUMKEYS*sizeof(Word_t));
    Word_t* range = malloc(NUMKEYS*sizeof(Word_t));
    
    srand(clock());
    
    printf("generate keys\n");
 
    Word_t startvalue = 6094748957;
    int i = 0;
    for (i = 0; i < NUMKEYS; ++i)
    {
        keys[i] = startvalue + (i * 133);
    }
    
    printf("insert keys first = %ull last = %ull\n",keys[0],keys[NUMKEYS-1]);
    
    clock_t start,stop;

    start = clock();
    for (i = 0; i < NUMKEYS; ++i)
    {
        JudyLIns(&array,keys[i],&err);
    }
    
    stop = clock();

    Word_t memused = JudyLMemUsed(array);
    printf("insert time = %0.9f avg = %0.9f memory = %0.2f mb\n",
        (float)(stop-start)/CLOCKS_PER_SEC,
        ((float)(stop-start)/CLOCKS_PER_SEC)/NUMKEYS,
        (float)memused / 1024 / 1024
    );
    
    start = clock();
    
    for(i = 0; i < NUMKEYS; ++i)
    {
        JudyLGet(&array,keys[i],&err);
    }
    
    stop = clock();
    printf("read time = %0.9f avg = %0.9f\n",
           (float)(stop-start)/CLOCKS_PER_SEC,
           ((float)(stop-start)/CLOCKS_PER_SEC)/NUMKEYS
           );
    
    start = clock();
    
    int j = 0;
    Word_t Index = 0;
    Word_t* PValue = NULL;
    JLF(PValue,array,Index);
    while (PValue != NULL)
    {
        range[j++] = Index;
        JLN(PValue,array,Index);
    }
    
    stop = clock();
    
    printf("range time = %0.9f avg = %0.9f items = %d\n",
           (float)(stop-start)/CLOCKS_PER_SEC,
           ((float)(stop-start)/CLOCKS_PER_SEC)/NUMKEYS,
           j
    );
    
    return 0;
}
Re[12]: std::map VS Dictionary.NET VS SortedDictionary.NET V
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 08.05.12 12:44
Оценка:
Здравствуйте, roro, Вы писали:

Спасибо за тест!
Такой вопрос, Джуди проверяет ключи на выход за диапазон ?
Ато вроде как на .NET обертке добавление двух одинаковых ключей убило всю структуру.
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re[12]: std::map VS Dictionary.NET VS SortedDictionary.NET V
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 08.05.12 13:15
Оценка:
Здравствуйте, roro, Вы писали:

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

Word_t startvalue = 6094748957;
R> int i = 0;
R> for (i = 0; i < NUMKEYS; ++i)
R> {
R> keys[i] = startvalue + (i * 133);
R> }

R>
R>word size = 8 numkeys = 1000000
R>generate keys
R>insert keys first = 1799781661ll last = 1932781528ll
R>insert time = 0.137306005 avg = 0.000000137 memory = 18.97 mb
R>read time = 0.011178000 avg = 0.000000011
R>range time = 0.041843001 avg = 0.000000042 items = 1000000
R>


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

int _tmain(int argc, _TCHAR* argv[])
{
    //20/21/22/23/24 /25 /26 /
    //19/14/9 /6 /3.7/2.7/2.4/
    clock_t start, finish;

    keys = new uint[COUNT_KEYS];

    /*FILE* file = fopen("c:\\rand.bin", "rb");

    uint maxOffset = 0;
    
    for(uint i=1; i<COUNT_KEYS; i++)
    {
        fread(&keys[i], 4, 1, file);
    }
    
    fclose(file);*/

    uint startvalue = 6094748957;
    int i = 0;
    for (i = 0; i < COUNT_KEYS; ++i)
    {
        keys[i] = startvalue + (i * 133);
    }

    init(27);

    /*
    uint* keys = new uint[COUNT_KEYS];
    uint* values = new uint[COUNT_KEYS];
    
    for(uint i=0; i<COUNT_KEYS; i++)
    {
        keys[i] = i;
        values[i] = i;
        count1 += i;
    }
    */

    start = clock();

    //368 mb //average for 15
    //372 mb //average for 10
    //383 mb //average for 5
    //423 mb //average for 1

    //( array(4 bytes value + 2 bytes key) + block(4bytes value + 2 bytes key)
    //12 bytes

    //init(keys, values, COUNT_KEYS);

    for(uint i=0; i<COUNT_KEYS; i++)
    {
        //if(i==4688209)
        //    printf( "%2.1d\n", i);
        
        insert(keys[i], keys[i]);
        //insert(i, i);
        //m[keys[i]] = keys[i];
        
        //4688210
        
        /*        
        if(i>9918351)
        for(uint j=0; j<=i; j++)
        {
            if(getValueByKey(keys[j]) != keys[j])
            {
                printf( "Error: %2.1d %2.1d\n", getValueByKey(j), j);
                return 0;
            }
        }
        */
    }

    finish = clock();

    //delete[] values;

    printf( "Filled: %2.1d msec\n", (finish - start) );

    start = clock();

    for(uint i=0; i<COUNT_KEYS; i++)
    {
        if( getValueByKey(keys[i]) != keys[i])
        {
            printf( "Error: %2.1d %2.1d\n", getValueByKey(keys[i]), keys[i]);
        }
    }
    
    finish = clock();

    delete[] keys;
    
    printf( "Searches: %2.1d msec\n", (finish - start) );
    printf( "CountDoublePage: %2.1d\n", CountDoublePage );
    printf( "CountMultiplyPage: %2.1d\n", CountMultiplyPage );
    printf( "Double size pages: %2.1d\n", CountDoublePage * sizeof(DoublePage));
    printf( "Multiply size pages: %2.1d\n", CountMultiplyPage * sizeof(MultiplyPage));
    printf( "Size pages: %2.1d\n", CountDoublePage * sizeof(DoublePage) + CountMultiplyPage * sizeof(MultiplyPage));
    
    uint* buff = new uint[COUNT_KEYS];

    start = clock();

    uint count = getValuesByRange(buff, COUNT_KEYS, 1, 0xFFFFFFFF);
    
    finish = clock();

    printf( "Range: %2.1d msec\n", (finish - start) );

    delete[] buff;
    
    printf( "Type1: %2.1d\n", type1 );
    printf( "Type2: %2.1d\n", type2 );
    printf( "Type3: %2.1d\n", type3 );
    printf( "TypeX: %2.1d\n", typeX );
    
    //2.8 1.3

    /*
    start = clock();

    uint* buffer = new uint[COUNT_KEYS];

    int idx = getValuesByRange(buffer, COUNT_KEYS, 0, COUNT_KEYS - 1);
    
    delete[] buffer;

    finish = clock();

    printf( "Search by range: %2.1d msec\n", (finish - start) );

    destroy();

    printf( "List: %2.1d bytes\n", COUNT_KEYS*4*2);

    */

    system("pause");

    return 0;
};



64 битных ключей у меня нет, есть пока 32х битные.
Поэтому просто, для начала, взял в два раза больше ключей (2 млн вместо 1 млн).
Результаты такие:

word size = 4 numkeys = 2000000
generate keys
insert keys first = 1799781661ll last = 1932781528ll
insert time = 0.041 avg = 0.000000041 memory ~30 mb
read time = 0.003 avg = 0.000000003
range time = 0.550 avg = 0.000000550 items = 2000000

У меня для этой последовательности тоже ключи феншуйно работают
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re[13]: std::map VS Dictionary.NET VS SortedDictionary.NET V
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 08.05.12 13:17
Оценка:
Процессор iCore 7,
тут добрые люди еще для семпрона Джуди протестили

http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&amp;tid=708039&amp;msg=12523337
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re[14]: std::map VS Dictionary.NET VS SortedDictionary.NET V
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 11.05.12 10:36
Оценка:
Здравствуйте, PC_2, Вы писали:

Попробую в ближайшие пару недель собрать поисковый движок
на базе алгоритма.
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re: std::map VS Dictionary.NET VS SortedDictionary.NET VS HArray
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.05.12 12:52
Оценка:
Здравствуйте, PC_2, Вы писали:
Посмотри Б деревья http://rsdn.ru/article/alg/tlsd.xml
Автор(ы): Сергей Смирнов (Serginio1)
Дата: 14.08.2004
Пример реализации двухуровневого массива с помощью нового средства С# — generics. Сравнение производительности различных реализаций сортированных списков.
и солнце б утром не вставало, когда бы не было меня
Re[2]: std::map VS Dictionary.NET VS SortedDictionary.NET VS HArray
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 11.05.12 14:59
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, PC_2, Вы писали:

S>Посмотри Б деревья http://rsdn.ru/article/alg/tlsd.xml
Автор(ы): Сергей Смирнов (Serginio1)
Дата: 14.08.2004
Пример реализации двухуровневого массива с помощью нового средства С# — generics. Сравнение производительности различных реализаций сортированных списков.


Разные Б деревья в плане скорости поиска/вставки не интересны.
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re: std::map VS Dictionary.NET VS SortedDictionary.NET VS HArray
От: minorlogic Украина  
Дата: 11.05.12 15:35
Оценка: 1 (1)
Если поиск и вставка константные и данные отсортированны (с возможностью быстрого обхода), то это революция в CS
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: std::map VS Dictionary.NET VS SortedDictionary.NET VS HArray
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 11.05.12 15:53
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Если поиск и вставка константные и данные отсортированны (с возможностью быстрого обхода), то это революция в CS


Ну да, немного занятно получилось.

Quick sort = Inserts + Full scan по сортированым данным.

Тоесть чтобы отсортировать допустим большой обьем данных,
можно вставить в структуру и сделать фуллскан и по времени даже может быть
какойто минимальный выиграш Эдакий побочный эффект алгоритма.
Правда следует отметить справедливости ради, что второй алгоритм с структурой данных,
будет требовать дополнительную память. Квик сорт же не ест доп память.
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re[3]: std::map VS Dictionary.NET VS SortedDictionary.NET VS HArray
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 12.05.12 06:47
Оценка:
Здравствуйте, PC_2, Вы писали:

PC_>Здравствуйте, Serginio1, Вы писали:


S>>Здравствуйте, PC_2, Вы писали:

S>>Посмотри Б деревья http://rsdn.ru/article/alg/tlsd.xml
Автор(ы): Сергей Смирнов (Serginio1)
Дата: 14.08.2004
Пример реализации двухуровневого массива с помощью нового средства С# — generics. Сравнение производительности различных реализаций сортированных списков.


PC_>Разные Б деревья в плане скорости поиска/вставки не интересны.

Ну почему же. Б+ деревья на больших данных немного уступают Хэш таблицам. При примененийй данных типа курсора
и вставок типа NavigateOrInsertDefault можно это время сократить в 2 раза. При больших данных и поиск происходит быстрее, т.к. верхние уровни находятся в кэше процессора. Так как на практике в основном происходит поиск а не вставки, то возможно дополнительно в поиску подключать и хэш таблицу уоторая бы хранила Ключ и Страницу на которой находится элемент. Это значительно сократит поиск.
и солнце б утром не вставало, когда бы не было меня
Re[4]: std::map VS Dictionary.NET VS SortedDictionary.NET VS HArray
От: PC_2 http://code.google.com/p/rsinterpretator/
Дата: 14.05.12 09:50
Оценка:
Здравствуйте, Serginio1, Вы писали:

PC_>>Разные Б деревья в плане скорости поиска/вставки не интересны.

S> Ну почему же. Б+ деревья на больших данных немного уступают Хэш таблицам. При примененийй данных типа курсора

На больших обьемах данных у хештаблиц коллизии ростут в экспоненциальном порядке.
Это первый недостаток. Второй, они не сортируют ключи и не позволяют делать выборки по диапазону.
Но по скорости вставки/выборки разные подвиды бинарных деревьев далеко или очень далеко.
К слову сказать у меня одна из модификаций префиксных деревьев и здесь тоже можно верхние уровни
размещать в ОЗУ.

S>и вставок типа NavigateOrInsertDefault можно это время сократить в 2 раза. При больших данных и поиск происходит быстрее, т.к. верхние уровни находятся в кэше процессора. Так как на практике в основном происходит поиск а не вставки, то возможно дополнительно в поиску подключать и хэш таблицу уоторая бы хранила Ключ и Страницу на которой находится элемент. Это значительно сократит поиск.


Глянул Вашу реализацию.
Ну чисто визуально, сравните Вашу функцию поиска по ключу:

public bool NavigateKey(K key)
{
  // Устанавливаем индекс элемента в 0.
  _currentElementIndex = 0; 
  // Если есть второй уровень...
  if (_pageCount > 1)
  {
    // Перебираем грани
    int hi = _pageCount - 1;

    int lo = 0;

    while (lo <=  hi)
    {
      int i = (lo +  hi) >> 1;
      int result = _comparer.Compare(NodeArray[i].Key, key);

      if (result < 0)
        lo = i + 1;
      else
      {
        hi = i - 1;
        if (result == 0)
        {
          // Ключ найден на 2 уровне. Устанавливаем текущую 
          // страницу CurrentLeafPage.
          _currentPageIndex = i;
          CurrentLeafPage = NodeArray[_currentPageIndex].ChildPage;
          _selected = true;
          return true;
        }
      }
    }

    // Ключ не найден на 2 уровне.
    // Проверяем на возможность того, что искомый ключ – 
    // наименьший из имеющихся в объекте.
    if (hi < 0)
    {
      // Данный ключ меньше наименьшего хранимого ключа.
      // Встаем на самый первый элемент двухуровневого массива 
      _currentPageIndex = 0;
      CurrentLeafPage = NodeArray[_currentPageIndex].ChildPage;
      _selected = false;
      // Возвращаем информацию о том, что ключ не найден.
      return false;
    }
    else
    {
      // Данный ключ попадает в диапазон ключей нижележащей страницы.
      // Изменяем текущую страницу CurrentLeafPage на найденную дочернюю
      // страницу 
      CurrentLeafPage = NodeArray[_currentPageIndex].ChildPage;
      // Устанавливаем текущий индекс ключа на листовой странице в 1, 
      // т.к. 0 уже проверяли.
      _currentElementIndex = 1;
    }
  }

  // Пытаемся найти индекс искомого ключа или индекс, в котором он должен
  // был находиться.
  hi = CurrentLeafPage.Count - 1;
  lo = _currentElementIndex;

  while (lo <= hi)
  {
    int i = (lo + hi) >> 1;
    int result = _comparer.Compare(CurrentLeafPage.PageItems[i].Key, key);

    if (result < 0)
      lo = i + 1;
    else
    {
      hi = i - 1;
      if (result == 0)
      {
        // Нашли!
        _currentElementIndex = i;
        _selected = true;
        return true;
      }
    }
  }

  // Не нашли... 
  _selected = false;
  // Помещаем в _currentElementIndex позицию в которую 
  // можно добавить элемент с искомым ключом.
  _currentElementIndex = lo;
  return false;
}


И мою функцию извлечения по ключу для строк

inline uint getValueByKey(char* key, uint base)
{
    ushort* pKey = (ushort*)key;
    Info* pParentInfo = pInfoRoot;

    for(uint i=0; i<base; i++)
        pParentInfo = pParentInfo->pBlockInfos[pKey[i]];
    
    //last iteration
    return ((InfoValue*)pParentInfo)->Value;
}


Теперь чисто визуально, сколько нужно первой реализации выполнить процессорных комманд, сделать дополнительных вызовов функций, копирований и тд
и моей реализации которая извлекает значение по ключу за О(1), внезависимости там 100 ключей или 100 млрд ключей.
Количество итераций в цикле зависит от длины ключа, например для ключа в 8 символов будет всегда константно 4 итерации.

Есть еще вырожденный вариант для 32 битных ключей

inline uint getValueByKeyInt32(uint key)
{
    return (uint)pInfoRoot->pBlockInfos[key&0xFFFF]->pBlockInfos[key>>16];
}


Как видите, здесь уж совсем экономный вариант.
Поиск чуть тяжелее чем прямое взятие элемента из массива по индексу и в некоторых случаях разгоняется до абсолютно
фантастических 2 наносекунд на один поиск (500 млн поисков в секунду).
"Вся страна играть в футбол умеет, лишь мы 11 человек играть не умеем"(с)КВН
Re[5]: std::map VS Dictionary.NET VS SortedDictionary.NET VS HArray
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.12 11:21
Оценка:
Здравствуйте, PC_2, Вы писали:



PC_>Теперь чисто визуально, сколько нужно первой реализации выполнить процессорных комманд, сделать дополнительных вызовов функций, копирований и тд

Ну я предлагал использовать Хэш таблицу для ключей в котором хранится ключ и страница Б+ дерева Что бы производить поиск не по дереву а на странице.
Но это не суть. Проблема при увеличении объемов данных не попадающих в Кэш процессора сильно уже зависит от медленной памяти. А соотношение времени вставки поиска Б+ деревья и Хэш таблицы остаются константными. Кстати если видел реализацию NavigateOrInsertDefault то там запоминаентся текущая позиция и при изменении значения вторичный поиск не производится. А по поводу выборки Б+ деревьев, то это прохождение по масииву. Обычно нужны выборки по диапозону, поиск на меньше или больше значения без равно итд. Все то, что используется в Базе. А также сравнение двух таблиц по индексам где сравнение идет не по поиску ключа а по сравнению текущих значений и продвижению по таблице с меньшим ключем, при равном двигаются оба курсора.
и солнце б утром не вставало, когда бы не было меня
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.