// The smallest unit of data loaded into memory PageSize = 4096, }; // Create table (string key - ascii comparer) var table1 = builder.CreateTable("items", KeyEncoding.Ascii); table1.Append("key1", "value1"u8.ToArray()); // value is any `Memory<byte>` table1.Append("key2", "value2"u8.ToArray()); table1.Append("key3", "value3"u8.ToArray()); table1.Append("key4", "value4"u8.ToArray()); // Build await builder.BuildToFileAsync("/path/to/bin.drydb");
キャッシュポリシーを選べない • OS の汎用 LRU はスキャン耐性が無く、索引ページの優先保持もできず、メモリ上限も不明 • 最大メモリ使用量をコントロールしずらい • 変換を挟めない • 圧縮・暗号化・チェックサムは「ディスク上とメモリ上でバイト列が違う」ことを要求するが、mmap は同一であることが前提 • TLB (Tlanslation Lookup Bu er) あふれ • 仮想メモリアドレス領域が大きくなると、仮想メモリアドレス → 物理アドレス 変換のためのテーブルがTLBにおさまらなくなり、 lookupコストが増大する ff Are You Sure You Want to Use MMAP in Your Database Management System? Andrew Crotty, Viktor Leis, Andy Pavlo ― CIDR 2022 https://db.cs.cmu.edu/mmap-cidr2022/
: IDisposable { public IPageEntry Page => entry; public int Start => start; public int Length => length; public ReadOnlySpan<byte> Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Page.Memory.Span.Slice(start, length); } public ReadOnlyMemory<byte> Memory { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Page.Memory.Slice(start, length); } } public void Dispose() { entry.Release(); } // return new PageSlice(lease.Take(), valueOffset, valueLength)
: IDisposable { public IPageEntry Page => entry; public int Start => start; public int Length => length; public ReadOnlySpan<byte> Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Page.Memory.Span.Slice(start, length); } 参照カウントでuse after freeは public ReadOnlyMemory<byte> Memory 防ぐ必要が… { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Page.Memory.Slice(start, length); } } public void Dispose() { entry.Release(); } // return new PageSlice(lease.Take(), valueOffset, valueLength)
var min = 0; var max = digests.Length; while (min < max) { var mid = min + ((max - min) >> 1); if (digests[mid] < target) min = mid + 1; else max = mid; } return min; }
target) { // 残り32要素までは普通に二分探索 var min = 0; var max = digests.Length; while (max - min > 32) { var mid = min + ((max - min) >> 1); if (digests[mid] < target) min = mid + 1; else max = mid; } ラスト32要素のみSIMDで線形探索 どこまでSIMD化するかは匙加減 // ラスト32要素はSIMDで力業! var start = max - 32; var targetVec = Vector128.Create(target); var acc0 = Vector128<ulong>.Zero; var acc1 = Vector128<ulong>.Zero; var acc2 = Vector128<ulong>.Zero; var acc3 = Vector128<ulong>.Zero; for (var i = start; i < max; i += 8) { acc0 -= Vector128.LessThan(LoadDigests(digests, i), targetVec); acc1 -= Vector128.LessThan(LoadDigests(digests, i + 2), targetVec); acc2 -= Vector128.LessThan(LoadDigests(digests, i + 4), targetVec); acc3 -= Vector128.LessThan(LoadDigests(digests, i + 6), targetVec); } var acc = (acc0 + acc1) + (acc2 + acc3); return start + (int)(acc.GetElement(0) + acc.GetElement(1)); }
Kperf = "/System/Library/PrivateFrameworks/kperf.framework/kperf"; const string KperfData = "/System/Library/PrivateFrameworks/kperfdata.framework/kperfdata"; public const int MaxCounters = 32; // ---- kperf: kernel PMU control (root required for kpc_force_all_ctrs_set) ---macOSの場合、kperfて [DllImport(Kperf)] public static extern int kpc_force_all_ctrs_set(int val); [DllImport(Kperf)] public static unsafe extern int kpc_set_config(uint classes, ulong* config); のがあるヨ [DllImport(Kperf)] public static extern int kpc_set_counting(uint classes); [DllImport(Kperf)] public static extern int kpc_set_thread_counting(uint classes); [DllImport(Kperf)] public static unsafe extern int kpc_get_thread_counters(uint tid, uint bufCount, ulong* buf); // ---- kperfdata: event database (/usr/share/kpep/*.plist) and register mapping ---[DllImport(KperfData)] public static unsafe extern int kpep_db_create(byte* name, out IntPtr db); [DllImport(KperfData)] public static extern int kpep_config_create(IntPtr db, out IntPtr cfg); [DllImport(KperfData)] public static extern int kpep_config_force_counters(IntPtr cfg); [DllImport(KperfData)] public static unsafe extern int kpep_db_event(IntPtr db, byte* name, out IntPtr ev); [DllImport(KperfData)] public static unsafe extern int kpep_config_add_event(IntPtr cfg, ref IntPtr ev, uint flag, uint* err); [DllImport(KperfData)] public static unsafe extern int kpep_config_kpc(IntPtr cfg, ulong* buf, nuint bufSizeBytes); [DllImport(KperfData)] public static extern int kpep_config_kpc_count(IntPtr cfg, out nuint count); [DllImport(KperfData)] public static extern int kpep_config_kpc_classes(IntPtr cfg, out uint classes); [DllImport(KperfData)] public static unsafe extern int kpep_config_kpc_map(IntPtr cfg, nuint* buf, nuint bufSizeBytes); }