monoclex / StringDB

StringDB is a modular, key/value pair archival DB designed to consume *tiny* amounts of ram & produce *tiny* databases.
MIT License
70 stars 12 forks source link

Exception on Concurrency Multi Reading and 1 Writeing ? #9

Closed sgf closed 2 years ago

sgf commented 2 years ago

most time Exception on TryGet Method.

the fllow is the test Code


               StringDBTest.TestFileNameLengthEffects0(); //Test Entry

public class StringDBTest {
        static StringDBTest() {
            try {
                //db = new LiteDatabase("Filename=TestDB.ldb;");//初始化数据库connection=shared
                db = new DatabaseBuilder()
                           .UseIODatabase(StringDBVersion.Latest, "StringDBTest.db", out var optimalTokenSource)
                           .WithBuffer(1000)
                           .WithTransform(StringTransformer.Default, StringTransformer.Default);
            } catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }
        }

        public static IDatabase<string, string> db;

        public static List<CTS1> DataGen(ref int current, int count) {
            List<CTS1> list = new(count);
            for (int i = 0; i < count; i++) {
                var val = (current + i);
                var key = $"0d3deed1234567890abcd{(100000000 - (current + i)):D12}";
                list.Add(new(key, val));
            }
            current = current + count;
            return list;
        }

        static Random r = new Random();

        public static async void SelectTest() {
            while (!IsExit()) {
                await Task.Delay(r.Next(1, 10));//随机触发查询时间
                var sw = Stopwatch.StartNew();
                var rs = r.Next(0, 10000000);
                var key = $"0d3deed1234567890abcd{(100000000 - rs):D12}";
                db.TryGet(key, out string strVal);
                //var rlt = db.Get(key);
                if (sw.Elapsed.Seconds > 1)
                    Console.WriteLine($"查询时间大于1秒-{sw.ElapsedMilliseconds}ms");
                Interlocked.Increment(ref QueryCount);
            }
        }

        public static bool IsExit() {
            return Interlocked.Read(ref exit) == 1;
        }

        static long exit = 0;

        public static long QueryCount;

        public static void TestFileNameLengthEffects0() {
            //using var db1 = new LiteDatabase("Filename=TestDB0.ldb;");
            var sw = Stopwatch.StartNew();
            var swOutput = Stopwatch.StartNew();
            for (int t = 0; t < 50; t++)
                Task.Factory.StartNew(SelectTest);
            int totalIdx = 26860000;
            for (int i = 0; i < 10000; i++) {
                var list = DataGen(ref totalIdx, 20000); //每2w一个批次
                try {
                   db.InsertRange(list.Select(cts=> new KeyValuePair<string,string>(cts.Code, cts.ToString())).ToArray());
                } catch (Exception ex) {
                    Console.WriteLine(ex.Message);
                }
                if (swOutput.Elapsed.TotalSeconds > 8) {
                    Console.WriteLine($" 当前数量:{totalIdx} 平均插入速度:{(totalIdx / sw.Elapsed.TotalSeconds)}op/s , 查询次数{(QueryCount / sw.Elapsed.TotalSeconds)}/s");
                    swOutput.Restart();
                }
            }
            exit = 1;
        }

        /// <summary>
        /// CodeTaskSmall
        /// </summary>
        public class CTS1 {
            public CTS1(string code, int taskId) {
                Code = code;
                TaskId = taskId;
            }
            [LiteDB.BsonId]
            public string Code;
            [LiteDB.BsonField("t")]
            public int TaskId;
        }

    }
monoclex commented 2 years ago

Sorry, but StringDB is not thread safe.

sgf commented 2 years ago

thanks