public TripleStore32(Func <Stream> stream_gen, string tmp_dir) { // Тип Object Variants PType tp_ov = new PTypeUnion( new NamedType("dummy", new PType(PTypeEnumeration.none)), new NamedType("iri", new PType(PTypeEnumeration.integer)), new NamedType("str", new PType(PTypeEnumeration.sstring))); tp_triple = new PTypeRecord( new NamedType("subj", new PType(PTypeEnumeration.integer)), new NamedType("pred", new PType(PTypeEnumeration.integer)), new NamedType("obj", tp_ov)); table = new UniversalSequenceBase(tp_triple, stream_gen()); var spo_comparer = Comparer <object> .Create(new Comparison <object>((object a, object b) => { object[] aa = (object[])a; object[] bb = (object[])b; int cmp = ((int)aa[0]).CompareTo((int)bb[0]); return(cmp); })); keyFunc = tri => (int)((object[])tri)[0]; index_spo = new UniversalSequenceCompKey32(stream_gen(), keyFunc, spo_comparer, table); indexTest = new IndexViewImmutable(stream_gen, table, Comparer <object> .Create(new Comparison <object>((object a, object b) => { object[] aa = (object[])a; object[] bb = (object[])b; int cmp = ((int)aa[0]).CompareTo((int)bb[0]); return(cmp); })), tmp_dir, 20_000_000 ); }
public Nametable32(Func <Stream> stream_gen) { PType tp_elem = new PTypeRecord( new NamedType("code", new PType(PTypeEnumeration.integer)), new NamedType("str", new PType(PTypeEnumeration.sstring))); cod_str = new UniversalSequenceBase(tp_elem, stream_gen()); offsets = new UniversalSequenceBase(new PType(PTypeEnumeration.longinteger), stream_gen()); index_str = new IndexKey32CompImmutable(stream_gen, cod_str, ob => true, ob => Hashfunctions.HashRot13((string)((object[])ob)[1]), null); dyna_index = new Dictionary <string, int>(); }
public void SaveFlowToSequence(IEnumerable <object> flow, string path) { var file = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite); UniversalSequenceBase sequ = new UniversalSequenceBase(tp_Record, file); sequ.Clear(); foreach (var ob in flow) { sequ.AppendElement(ob); } sequ.Flush(); file.Close(); }
// Конструктор public Mag_Triple_Store(Stream tab_stream, Stream spo_stream, Comparer <object> comp) { this.spo_comparer = comp; tp_triple = new PTypeRecord( new NamedType("subj", new PType(PTypeEnumeration.integer)), new NamedType("pred", new PType(PTypeEnumeration.integer)), new NamedType("obj", tp_ov)); table = new UniversalSequenceBase(tp_triple, tab_stream); spo_comparer = Comparer <object> .Create(new Comparison <object>((object a, object b) => { object[] aa = (object[])a; object[] bb = (object[])b; int cmp = ((int)aa[0]).CompareTo((int)bb[0]); return(cmp); })); index_spo = new UniversalSequenceComp(new PType(PTypeEnumeration.longinteger), spo_stream, spo_comparer, table); }
public Nametable32(Func <Stream> stream_gen) { PType tp_elem = new PTypeRecord( new NamedType("code", new PType(PTypeEnumeration.integer)), new NamedType("str", new PType(PTypeEnumeration.sstring))); table = new UniversalSequenceBase(tp_elem, stream_gen()); str_offsets = new UniversalSequence <long>(new PType(PTypeEnumeration.longinteger), stream_gen()); Comparer <object> comp_str = Comparer <object> .Create(new Comparison <object>((object a, object b) => { var aa = (string)((object[])a)[1]; var bb = (string)((object[])b)[1]; return(aa.CompareTo(bb)); })); name_index = new IndexKey32CompImm(stream_gen, table, ob => Hashfunctions.HashRot13((string)((object[])ob)[1]), comp_str); dyna_index = new Dictionary <string, int>(); }
public TripleStoreInt32_(Func <Stream> stream_gen) { // Тип Object Variants PType tp_ov = new PTypeUnion( new NamedType("dummy", new PType(PTypeEnumeration.none)), new NamedType("iri", new PType(PTypeEnumeration.integer)), new NamedType("str", new PType(PTypeEnumeration.sstring))); PType tp_triple = new PTypeRecord( new NamedType("subj", new PType(PTypeEnumeration.integer)), new NamedType("pred", new PType(PTypeEnumeration.integer)), new NamedType("obj", tp_ov)); table = new UniversalSequenceBase(tp_triple, stream_gen()); s_index = new IndexKey32CompImm(stream_gen, table, ob => (int)((object[])ob)[0], null); string selected_chars = "!\"#$%&\'()*+,-./0123456789:;<=>?@abcdefghjklmnopqrstuwxyz{|}~абвгдежзийклмнопрстуфхцчшщъыьэюяё"; Func <object, int> halfKeyFun = ob => { object[] tri = (object[])ob; object[] pair = (object[])tri[2]; int tg = (int)pair[0]; if (tg == 1) // iri { return(1 - (int)pair[1]); } else if (tg == 2) // str { string s = (string)pair[1]; int len = s.Length; var chs = s.ToCharArray() .Concat(Enumerable.Repeat(' ', len < 4 ? 4 - len : 0)) .Take(4) .Select(ch => { int ind = selected_chars.IndexOf(ch); if (ind == -1) { ind = 0; // неизвестный символ помечается как '!' } return(ind); }).ToArray(); return((chs[0] << 24) | (chs[1] << 16) | (chs[2] << 8) | chs[3]); } throw new Exception("Err: 292333"); }; Test_keyfun = halfKeyFun; Comparer <object> comp = Comparer <object> .Create(new Comparison <object>((object a, object b) => { object[] aa = (object[])((object[])a)[2]; object[] bb = (object[])((object[])b)[2]; int a1 = (int)aa[0]; int b1 = (int)bb[0]; int cmp = a1.CompareTo(b1); if (cmp != 0) { return(cmp); } if (a1 == 1) { return(((int)aa[1]).CompareTo(((int)bb[1]))); } return(((string)aa[1]).CompareTo(((string)bb[1]))); })); o_index = new IndexKey32CompImm(stream_gen, table, halfKeyFun, comp); }
public static void Main303() { Console.WriteLine("Start Main303"); // Создадим типы записи и последовательности записей PType tp_rec = new PTypeRecord( new NamedType("id", new PType(PTypeEnumeration.integer)), new NamedType("name", new PType(PTypeEnumeration.sstring)), new NamedType("age", new PType(PTypeEnumeration.integer))); PType tp_seq = new PTypeSequence(tp_rec); // ======== Универсальная последовательность ========== Stream stream = File.Open(datadirectory_path + "data303.bin", FileMode.OpenOrCreate); UniversalSequenceBase sequence = new UniversalSequenceBase(tp_rec, stream); Random rnd = new Random(); int nelements = 10_000_000; // При заполнении массива, сохраним офсеты элементов в массиве long[] offsets = new long[nelements]; int[] keys = new int[nelements]; bool toload = true; if (toload) { sw.Restart(); sequence.Clear(); for (int i = 0; i < nelements; i++) { int key = nelements - i - 1; offsets[i] = sequence.AppendElement(new object[] { key, "Иванов" + key, rnd.Next(1, 110) }); keys[i] = key; } // отсортируем пару массивов keys, offsets по ключам Array.Sort(keys, offsets); sw.Stop(); Console.WriteLine($"Load of {nelements} elements. duration={sw.ElapsedMilliseconds}"); } else { int ind = 0; sequence.Scan((off, obj) => { offsets[ind] = off; keys[ind] = (int)((object[])obj)[0]; ind++; return(true); }); // отсортируем пару массивов keys, offsets по ключам Array.Sort(keys, offsets); } // Будем делать выборку элементов по ключу sw.Restart(); int ntests = 1000; for (int j = 0; j < ntests; j++) { int key = rnd.Next(nelements); int nom = Array.BinarySearch(keys, key); long off = offsets[nom]; object[] fields = (object[])sequence.GetElement(off); if (key != (int)fields[0]) { throw new Exception("1233eddf"); } //Console.WriteLine($"key={key} {fields[0]} {fields[1]} {fields[2]}"); } sw.Stop(); Console.WriteLine($"duration of {ntests} tests is {sw.ElapsedMilliseconds} ms."); }
public TripleStoreInt32(Func <Stream> stream_gen) { // сначала таблица имен nt = new Nametable32(stream_gen); // Тип Object Variants PType tp_ov = new PTypeUnion( new NamedType("dummy", new PType(PTypeEnumeration.none)), new NamedType("iri", new PType(PTypeEnumeration.integer)), new NamedType("str", new PType(PTypeEnumeration.sstring)), new NamedType("int", new PType(PTypeEnumeration.sstring)), new NamedType("date", new PType(PTypeEnumeration.sstring)), new NamedType("langstr", new PTypeRecord( new NamedType("lang", new PType(PTypeEnumeration.sstring)), new NamedType("str", new PType(PTypeEnumeration.sstring))))); PType tp_triple = new PTypeRecord( new NamedType("subj", new PType(PTypeEnumeration.integer)), new NamedType("pred", new PType(PTypeEnumeration.integer)), new NamedType("obj", tp_ov)); // Главная последовательность кодированных триплетов table = new UniversalSequenceBase(tp_triple, stream_gen()); // прямой ссылочный индекс s_index = new IndexKey32CompImmutable(stream_gen, table, ob => Enumerable.Repeat <int>((int)((object[])ob)[0], 1), null); // Обратный ссылочный индекс i_index = new IndexKey32Imm(stream_gen, table, obj => { object[] pair = (object[])((object[])obj)[2]; int tg = (int)pair[0]; if (tg != 1) { return(Enumerable.Empty <int>()); } return(Enumerable.Repeat <int>((int)pair[1], 1)); }, null); // Индекс по тексту объектов триплетов с предикатом http://fogid.net/o/name Comparer <object> comp = Comparer <object> .Create(new Comparison <object>((object a, object b) => { return(string.Compare((string)((object[])((object[])a)[2])[1], (string)((object[])((object[])b)[2])[1])); })); int name_code = Int32.MinValue; // nt.GetSetStr("http://fogid.net/o/name"); // Такое предварительное вычисление не работает!!! name_index = new IndexKey32CompImmutable(stream_gen, table, obj => { if (name_code == Int32.MinValue) { name_code = nt.GetSetStr("http://fogid.net/o/name"); } object[] tri = (object[])obj; //TODO: кодов имени может быть много... if ((int)tri[1] != name_code) { return(Enumerable.Empty <int>()); } object[] pair = (object[])tri[2]; int tg = (int)pair[0]; string data = null; if (tg == 2) { data = (string)pair[1]; } //else if (tg == 5) data = (string)((object[])pair[1])[1]; // пока будем работать только с простыми строками if (data != null) { return(Enumerable.Repeat <int>(Hashfunctions.First4charsRu(data), 1)); } return(Enumerable.Empty <int>()); }, //new int[] { Hashfunctions.First4charsRu((string)((object[])obj)[1]) } comp); }
public static void Main402() { Console.WriteLine("Start Main402"); // Создадим типы записи и последовательности записей PType tp_rec = new PTypeRecord( new NamedType("id", new PType(PTypeEnumeration.integer)), new NamedType("name", new PType(PTypeEnumeration.sstring)), new NamedType("age", new PType(PTypeEnumeration.integer))); PType tp_seq = new PTypeSequence(tp_rec); // ======== Универсальная последовательность ========== Stream stream = File.Open(datadirectory_path + "first_data.bin", FileMode.OpenOrCreate); UniversalSequenceBase sequence = new UniversalSequenceBase(tp_rec, stream); Random rnd = new Random(); int nelements = 100_000; // Последовательность создается пустой или она может быть очищена sequence.Clear(); // В последовательность можно добавлять элементы в объектном представлении for (int i = 0; i < nelements; i++) { sequence.AppendElement(new object[] { i, "Иванов" + i, rnd.Next(1, 110) }); } // Серию записей обязательно надо завершать сбросом буферов sequence.Flush(); // Изучим полученную последовательность Console.WriteLine($"Count={sequence.Count()}"); foreach (object[] r in sequence.ElementValues().Skip(50_000).Take(20)) { Console.WriteLine($"{r[0]} {r[1]} {r[2]} "); } // При заполнении массива, сохраним офсеты элементов в массиве long[] offsets = new long[nelements]; int[] keys = new int[nelements]; sequence.Clear(); for (int i = 0; i < nelements; i++) { int key = nelements - i - 1; offsets[i] = sequence.AppendElement(new object[] { key, "Иванов" + key, rnd.Next(1, 110) }); keys[i] = key; } // отсортируем пару массивов keys, offsets по ключам Array.Sort(keys, offsets); // Будем делать выборку элементов по ключу sw.Restart(); int ntests = 10_000; for (int j = 0; j < ntests; j++) { int key = rnd.Next(nelements); int ind = Array.BinarySearch(keys, key); long off = offsets[ind]; object[] fields = (object[])sequence.GetElement(off); //Console.WriteLine($"key={key} {fields[0]} {fields[1]} {fields[2]}"); } sw.Stop(); Console.WriteLine($"duration of {ntests} tests is {sw.ElapsedMilliseconds} ms."); }
public static void Main15() { string path = "../../../"; Random rnd = new Random(); int cnt = 0; System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); Console.WriteLine("Start Main15"); Func <Stream> streamGen = () => new FileStream(path + "Databases/g" + (cnt++) + ".bin", FileMode.OpenOrCreate, FileAccess.ReadWrite); PType tp_person = new PTypeRecord( new NamedType("id", new PType(PTypeEnumeration.integer)), new NamedType("name", new PType(PTypeEnumeration.sstring)), new NamedType("years", new PType(PTypeEnumeration.real))); Comparer <object> comp_string = Comparer <object> .Create(new Comparison <object>((object a, object b) => { var aa = (string)((object[])a)[1]; var bb = (string)((object[])b)[1]; return(aa.CompareTo(bb)); })); UniversalSequenceBase table = new UniversalSequenceBase(tp_person, streamGen()); IndexKey32CompImm id_index = new IndexKey32CompImm(streamGen, table, ob => (int)((object[])ob)[0], null); //IndexKey32CompImm namehash_index = new IndexKey32CompImm(streamGen, table, // ob => Hashfunctions.HashRot13((string)((object[])ob)[1]), null); //IndexKey32CompImm namehash_index_full = new IndexKey32CompImm(streamGen, table, // ob => Hashfunctions.HashRot13((string)((object[])ob)[1]), comp_string); IndexViewImmutable nameview_index = new IndexViewImmutable(streamGen, table, comp_string, path + "Databases/", 50_000_000); int nelements = 1_000_000; Console.WriteLine($" nelements={nelements}"); // Загрузка bool toload = true; if (toload) { sw.Restart(); var dataflow = Enumerable.Range(0, nelements) .Select(nom => new object[] { nelements - nom - 1, "" + (nelements - nom - 1), rnd.NextDouble() * 100D }); table.Clear(); foreach (object[] element in dataflow) { table.AppendElement(element); } table.Flush(); id_index.Build(); //namehash_index.Build(); //namehash_index_full.Build(); nameview_index.Build(); sw.Stop(); Console.WriteLine($"Indexes ok. duration={sw.ElapsedMilliseconds}"); } else { sw.Restart(); table.Refresh(); id_index.Refresh(); //namehash_index.Refresh(); //namehash_index_full.Refresh(); nameview_index.Refresh(); sw.Stop(); Console.WriteLine($"refresh {nelements} ok. duration={sw.ElapsedMilliseconds}"); } int id = nelements * 2 / 3; int nprobe = 1000; int total = 0; var query1 = id_index.GetAllBySample(new object[] { id, null, -1.0D }); foreach (var obj in query1) { Console.WriteLine(tp_person.Interpret(obj)); } sw.Restart(); for (int i = 0; i < nprobe; i++) { id = rnd.Next(nelements); total += id_index.GetAllBySample(new object[] { id, null, -1.0D }).Count(); } sw.Stop(); Console.WriteLine($"GetById {nprobe} probes. duration={sw.ElapsedMilliseconds}"); // Работаем с именами string name = "" + (nelements * 2 / 3); //var query2 = namehash_index.GetAllBySample(new object[] { -1, name, -1.0D }); //foreach (var obj in query2) Console.WriteLine(tp_person.Interpret(obj)); //total = 0; //sw.Restart(); //for (int i = 0; i < nprobe; i++) //{ // name = "" + rnd.Next(nelements); // total += namehash_index.GetAllBySample(new object[] { -1, name, -1.0D }).Count(); //} //sw.Stop(); //Console.WriteLine($"GetByNameHash {nprobe} probes. duration={sw.ElapsedMilliseconds} total={total}"); // Работаем с именами и компаратором //name = "" + (nelements / 3); //var query3 = namehash_index_full.GetAllBySample(new object[] { -1, name, -1.0D }); //foreach (var obj in query3) Console.WriteLine(tp_person.Interpret(obj)); //total = 0; //sw.Restart(); //for (int i = 0; i < nprobe; i++) //{ // name = "" + rnd.Next(nelements); // total += namehash_index_full.GetAllBySample(new object[] { -1, name, -1.0D }).Count(); //} //sw.Stop(); //Console.WriteLine($"GetByNameHash Full {nprobe} probes. duration={sw.ElapsedMilliseconds} total={total}"); // Работаем с view индексом name = "" + (nelements * 2 / 3); var query4 = nameview_index.SearchAll(new object[] { -1, name, -1.0D }); foreach (var obj in query4) { Console.WriteLine(tp_person.Interpret(obj)); } nprobe = 1000; total = 0; sw.Restart(); for (int i = 0; i < nprobe; i++) { name = "" + rnd.Next(nelements); total += nameview_index.SearchAll(new object[] { -1, name, -1.0D }).Count(); } sw.Stop(); Console.WriteLine($"IndexView search for {nprobe} probes. duration={sw.ElapsedMilliseconds} total={total}"); }
public static void Demo101() { Console.WriteLine("Start Demo101"); // === Демонстрация базовых действий со структурами === // Создаем тип персоны PType tp_person = new PTypeRecord( new NamedType("id", new PType(PTypeEnumeration.integer)), new NamedType("name", new PType(PTypeEnumeration.sstring)), new NamedType("age", new PType(PTypeEnumeration.integer))); // делаем персону в объектном представлении object ivanov = new object[] { 7001, "Иванов", 20 }; // интерпретируем объект в контексте типа Console.WriteLine(tp_person.Interpret(ivanov, true)); // то же, но без имен полей Console.WriteLine(tp_person.Interpret(ivanov)); Console.WriteLine(); // Создадим поток байтов. Это мог бы быть файл: MemoryStream mstream = new MemoryStream(); // Поработаем через текстовый интерфейс TextWriter tw = new StreamWriter(mstream); TextFlow.Serialize(tw, ivanov, tp_person); tw.Flush(); // Прочитаем то что записали TextReader tr = new StreamReader(mstream); mstream.Position = 0L; string instream = tr.ReadToEnd(); Console.WriteLine($"======== instream={instream}"); Console.WriteLine(); // Теперь десериализуем ivanov = null; mstream.Position = 0L; ivanov = TextFlow.Deserialize(tr, tp_person); // проинтерпретируем объект и посмотрим Console.WriteLine(tp_person.Interpret(ivanov)); Console.WriteLine(); // ===== Последовательности ===== // Создаем тип последовательности персон PType tp_persons = new PTypeSequence(tp_person); // Сделаем генератор персон Random rnd = new Random(); Func <int, IEnumerable <object> > GenPers = nper => Enumerable.Range(0, nper) .Select(i => new object[] { i, "Иванов_" + i, rnd.Next(130) }); // Сгенерируем пробу и проинтерпретируем object sequobj = GenPers(20).ToArray(); Console.WriteLine(tp_persons.Interpret(sequobj)); Console.WriteLine(); // Чем плохо такое решение? Тем, что весь большой объект (последовательность записей) разворачивается в ОЗУ // Более экономным, как правило, является использование последовательностей string dbpath = @"D:/Home/data/GetStarted/"; Stream filestream = new FileStream(dbpath + "db0.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite); UniversalSequenceBase usequence = new UniversalSequenceBase(tp_person, filestream); // Последовательность можно очистить, в нее можно добавлять элементы, в конце добавлений нужно сбросить буфер int npersons = 1_000_000; usequence.Clear(); foreach (object record in GenPers(npersons)) { usequence.AppendElement(record); } usequence.Flush(); // Теперь можно сканировать последовательность int totalages = 0; usequence.Scan((off, ob) => { totalages += (int)((object[])ob)[2]; return(true); }); Console.WriteLine($"total ages = {totalages}"); //// Можно прочитать i-ый элемент //int ind = npersons * 2 / 3; //object ores = usequence.GetByIndex(ind); //Console.WriteLine($"element={tp_person.Interpret(ores)}"); //// Но нет - облом: Размер элемента не фиксирован (есть строка), к таким элементам по индексу обращаться не надо }
public static void Main306() { Console.WriteLine("Start Main306"); // Создадим типы записи и последовательности записей PType tp_rec = new PTypeRecord( new NamedType("id", new PType(PTypeEnumeration.integer)), new NamedType("name", new PType(PTypeEnumeration.sstring)), new NamedType("age", new PType(PTypeEnumeration.integer))); PType tp_seq = new PTypeSequence(tp_rec); // ======== Универсальная последовательность ========== Stream stream = File.Open(datadirectory_path + "data306.bin", FileMode.OpenOrCreate); Stream stream2 = File.Open(datadirectory_path + "keys306.bin", FileMode.OpenOrCreate); Stream stream3 = File.Open(datadirectory_path + "offsets306.bin", FileMode.OpenOrCreate); UniversalSequenceBase sequence = new UniversalSequenceBase(tp_rec, stream); UniversalSequenceBase sequence2 = new UniversalSequenceBase(new PType(PTypeEnumeration.integer), stream2); UniversalSequenceBase sequence3 = new UniversalSequenceBase(new PType(PTypeEnumeration.longinteger), stream3); Random rnd = new Random(); int nelements = 100_000_000; // При заполнении массива, сохраним офсеты элементов в массиве long[] offsets = new long[nelements]; int[] keys = new int[nelements]; bool toload = true; if (toload) { sw.Restart(); sequence.Clear(); for (int i = 0; i < nelements; i++) { int key = nelements - i - 1; offsets[i] = sequence.AppendElement(new object[] { key, "Иванов" + key, rnd.Next(1, 110) }); keys[i] = key; } sequence.Flush(); // отсортируем пару массивов keys, offsets по ключам Array.Sort(keys, offsets); // запишем массивы в последовательности sequence2.Clear(); for (int i = 0; i < nelements; i++) { sequence2.AppendElement(keys[i]); } sequence2.Flush(); sequence3.Clear(); for (int i = 0; i < nelements; i++) { sequence3.AppendElement(offsets[i]); } sequence3.Flush(); sw.Stop(); Console.WriteLine($"Load of {nelements} elements. duration={sw.ElapsedMilliseconds}"); } // Сначала сделаем единичный тест int k = nelements * 2 / 3; long ind = BinarySequenceSearchFirst(0, nelements, k, sequence2); long offf = (long)sequence3.GetByIndex(ind); object rec = sequence.GetElement(offf); Console.WriteLine($"k={k}, v={tp_rec.Interpret(rec)}"); // Будем делать выборку элементов по ключу sw.Restart(); int ntests = 1000; for (int j = 0; j < ntests; j++) { int key = rnd.Next(nelements); long nom1 = BinarySequenceSearchFirst(0, nelements, key, sequence2); long off = (long)sequence3.GetByIndex(nom1); object[] fields = (object[])sequence.GetElement(off); if (key != (int)fields[0]) { throw new Exception("1233eddf"); } } sw.Stop(); Console.WriteLine($"duration of {ntests} tests is {sw.ElapsedMilliseconds} ms."); }
// 10 тыс. элементов загрузка 5.4 сек. выборка 1 тыс. 97 мсек. // 100 тыс. элементов загрузка 71 сек. выборка 1 тыс. 25 сек. private static long BinarySequenceSearchFirst(long start, long number, int key, UniversalSequenceBase seq) { long half = number / 2; int middle_keyvalue = (int)seq.GetByIndex(start + half); if (half == 0) // number = 0, 1 { if ((int)seq.GetByIndex(start) == key) { return(start); } else if ((int)seq.GetByIndex(start + 1) == key) { return(start + 1); } else { return(-1); } } if (middle_keyvalue == key) { return(start + half); } long middle = start + half; long rest = number - half - 1; var middle_depth = middle_keyvalue - key; if (middle_depth == 0) // Нашли! { return(middle); } if (middle_depth < 0) { return(BinarySequenceSearchFirst(middle + 1, rest, key, seq)); } else { return(BinarySequenceSearchFirst(start, half, key, seq)); } }
public static void Main302() { Console.WriteLine("Start Main302"); // Создадим типы записи и последовательности записей PType tp_rec = new PTypeRecord( new NamedType("id", new PType(PTypeEnumeration.integer)), new NamedType("name", new PType(PTypeEnumeration.sstring)), new NamedType("age", new PType(PTypeEnumeration.integer))); PType tp_seq = new PTypeSequence(tp_rec); // ======== Универсальная последовательность ========== Stream stream = File.Open(datadirectory_path + "first_data.bin", FileMode.OpenOrCreate); UniversalSequenceBase sequence = new UniversalSequenceBase(tp_rec, stream); Random rnd = new Random(); int nelements = 10_000_000; // Последовательность создается пустой или она может быть очищена sequence.Clear(); // В последовательность можно добавлять элементы в объектном представлении for (int i = 0; i < nelements; i++) { sequence.AppendElement(new object[] { i, "Иванов" + i, rnd.Next(1, 110) }); } // Серию записей обязательно надо завершать сбросом буферов sequence.Flush(); // Изучим полученную последовательность Console.WriteLine($"Count={sequence.Count()}"); foreach (object[] r in sequence.ElementValues().Skip(50_000).Take(20)) { Console.WriteLine($"{r[0]} {r[1]} {r[2]} "); } sw.Restart(); long sum = 0; foreach (object[] r in sequence.ElementValues()) { sum += (int)r[2]; } sw.Stop(); Console.WriteLine($"scan of {nelements} duration {sw.ElapsedMilliseconds} ms. sum={sum}"); sw.Restart(); sum = 0; foreach (object[] r in Enumerable.Range(0, nelements).Select(i => new object[] { i, "Иванов" + i, 55 })) { sum += (int)r[2]; } sw.Stop(); Console.WriteLine($"object flow generation of {nelements} duration {sw.ElapsedMilliseconds} ms. sum={sum}"); sw.Restart(); sum = 0; foreach (var r in Enumerable.Range(0, nelements).Select(i => new AAA() { id = i, name = "Иванов" + i, age = rnd.Next(1, 110) })) { sum += (int)r.age; } sw.Stop(); Console.WriteLine($"struct flow generation of {nelements} duration {sw.ElapsedMilliseconds} ms. sum={sum}"); sw.Restart(); sum = 0; foreach (var r in Enumerable.Range(0, nelements).Select(i => new Tuple <int, string, int>(i, "Иванов" + i, rnd.Next(1, 110)))) { sum += r.Item3; } sw.Stop(); Console.WriteLine($"tuple flow generation of {nelements} duration {sw.ElapsedMilliseconds} ms. sum={sum}"); sw.Restart(); sum = 0; foreach (var r in Enumerable.Range(0, nelements).Select(i => new Tuple <int, long, int>(i, (long)i, rnd.Next(1, 110)))) { sum += r.Item3; } sw.Stop(); Console.WriteLine($"allint tuple flow generation of {nelements} duration {sw.ElapsedMilliseconds} ms. sum={sum}"); sw.Restart(); sum = 0; foreach (var r in Enumerable.Range(0, nelements).Select(i => new object[] { i, (long)i, rnd.Next(1, 110) })) { sum += (int)r[2]; } sw.Stop(); Console.WriteLine($"allint object flow generation of {nelements} duration {sw.ElapsedMilliseconds} ms. sum={sum}"); sw.Restart(); sum = 0; foreach (var r in Enumerable.Range(0, nelements).Select(i => 55)) { sum += (int)r; } sw.Stop(); Console.WriteLine($"int flow generation of {nelements} duration {sw.ElapsedMilliseconds} ms. sum={sum}"); //scan of 10000000 duration 2133 ms.sum = 549806436 //object flow generation of 10000000 duration 858 ms.sum = 550000000 //struct flow generation of 10000000 duration 810 ms.sum=550058422 //tuple flow generation of 10000000 duration 837 ms.sum=549922381 //allint tuple flow generation of 10000000 duration 279 ms.sum=550001434 //allint object flow generation of 10000000 duration 501 ms.sum=549901363 //int flow generation of 10000000 duration 118 ms.sum=550000000 return; // При заполнении массива, сохраним офсеты элементов в массиве long[] offsets = new long[nelements]; int[] keys = new int[nelements]; sequence.Clear(); for (int i = 0; i < nelements; i++) { int key = nelements - i - 1; offsets[i] = sequence.AppendElement(new object[] { key, "Иванов" + key, rnd.Next(1, 110) }); keys[i] = key; } // отсортируем пару массивов keys, offsets по ключам Array.Sort(keys, offsets); // Будем делать выборку элементов по ключу sw.Restart(); int ntests = 10_000; for (int j = 0; j < ntests; j++) { int key = rnd.Next(nelements); int ind = Array.BinarySearch(keys, key); long off = offsets[ind]; object[] fields = (object[])sequence.GetElement(off); //Console.WriteLine($"key={key} {fields[0]} {fields[1]} {fields[2]}"); } sw.Stop(); Console.WriteLine($"duration of {ntests} tests is {sw.ElapsedMilliseconds} ms."); }