コード例 #1
0
        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.");
        }
コード例 #2
0
        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)}");
            //// Но нет - облом: Размер элемента не фиксирован (есть строка), к таким элементам по индексу обращаться не надо
        }