Skip to content

Commit

Permalink
Merge eac10e2 into d0e96d3
Browse files Browse the repository at this point in the history
  • Loading branch information
dasatomic committed Dec 8, 2021
2 parents d0e96d3 + eac10e2 commit 0889578
Show file tree
Hide file tree
Showing 47 changed files with 663 additions and 72 deletions.
63 changes: 48 additions & 15 deletions DataStructures/BTreeCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class BTreeCollection : IPageCollection<RowHolder>
private Func<MixedPage, string> debugPrintPage;

private int indexPosition;
private Action<MixedPage, RowHolder, ITransaction> rowUniqueCheckPageLevel = null;

public BTreeCollection(IAllocateMixedPage pageAllocator, ColumnInfo[] columnTypes, ITransaction tran, Func<RowHolder, RowHolder, int> indexComparer, int indexPosition)
{
Expand Down Expand Up @@ -74,6 +75,9 @@ public BTreeCollection(IAllocateMixedPage pageAllocator, ColumnInfo[] columnType
}

this.projectionRemoveIndexCol = new ProjectExtendInfo(mps, prjs, new ColumnInfo[0]);
this.rowUniqueCheckPageLevel = ColumnTypeHandlerRouter<Action<MixedPage, RowHolder, ITransaction>>.Route(
new BTreeUniqueCheckCreator { IndexPosition = this.indexPosition },
this.btreeColumnTypes[this.indexPosition].ColumnType);
}

public BTreeCollection(IAllocateMixedPage pageAllocator, ColumnInfo[] columnTypes, Func<RowHolder, RowHolder, int> indexComparer, int indexPosition, ulong initialPageId, ITransaction tran)
Expand Down Expand Up @@ -122,6 +126,10 @@ public BTreeCollection(IAllocateMixedPage pageAllocator, ColumnInfo[] columnType
}

this.projectionRemoveIndexCol = new ProjectExtendInfo(mps, prjs, new ColumnInfo[0]);

this.rowUniqueCheckPageLevel = ColumnTypeHandlerRouter<Action<MixedPage, RowHolder, ITransaction>>.Route(
new BTreeUniqueCheckCreator { IndexPosition = this.indexPosition },
this.btreeColumnTypes[this.indexPosition].ColumnType);
}

public async Task Add(RowHolder item, ITransaction tran)
Expand Down Expand Up @@ -176,18 +184,9 @@ public async Task Add(RowHolder item, ITransaction tran)

if (currPage.RowCount() < this.maxElemsPerPage)
{
// check if element exists.
foreach (RowHolder rh in currPage.Fetch(tran))
{
int compareResult = this.indexComparer(itemToInsert, rh);

if (compareResult == 0)
{
throw new KeyAlreadyExists();
}
}
this.rowUniqueCheckPageLevel(currPage, itemToInsert, tran);

int pos = currPage.InsertOrdered(itemToInsert, tran, this.btreeColumnTypes, this.indexComparer);
int pos = currPage.InsertOrdered(itemToInsert, tran, this.btreeColumnTypes, this.indexPosition);
Debug.Assert(pos >= 0);

if (debugPrintPage != null)
Expand All @@ -210,12 +209,12 @@ public async Task Add(RowHolder item, ITransaction tran)
if (compareResult < 0)
{
// left.
int pos = currPage.InsertOrdered(itemToInsert, tran, this.btreeColumnTypes, this.indexComparer);
int pos = currPage.InsertOrdered(itemToInsert, tran, this.btreeColumnTypes, this.indexPosition);
}
else
{
// right.
int pos = newPageForSplit.InsertOrdered(itemToInsert, tran, this.btreeColumnTypes, this.indexComparer);
int pos = newPageForSplit.InsertOrdered(itemToInsert, tran, this.btreeColumnTypes, this.indexPosition);
}

insertFinished = true;
Expand Down Expand Up @@ -422,7 +421,7 @@ private async Task<RowHolder> SplitBtreePage(MixedPage currPage, MixedPage newPa

if (prevPage != null)
{
int pos = prevPage.InsertOrdered(rowHolderForSplit, tran, this.btreeColumnTypes, this.indexComparer);
int pos = prevPage.InsertOrdered(rowHolderForSplit, tran, this.btreeColumnTypes, this.indexPosition);

// We know that there will be enough space since we proactivly clean parent nodes.
Debug.Assert(pos >= 0);
Expand All @@ -436,7 +435,7 @@ private async Task<RowHolder> SplitBtreePage(MixedPage currPage, MixedPage newPa
MixedPage newRoot = await pageAllocator.AllocateMixedPage(this.btreeColumnTypes, PageManagerConstants.NullPageId, PageManagerConstants.NullPageId, tran);
this.SetLeaf(newRoot, false);
using Releaser newRootLock = await tran.AcquireLock(newPageForSplit.PageId(), LockManager.LockTypeEnum.Exclusive).ConfigureAwait(false);
int pos = newRoot.InsertOrdered(rowHolderForSplit, tran, this.btreeColumnTypes, this.indexComparer);
int pos = newRoot.InsertOrdered(rowHolderForSplit, tran, this.btreeColumnTypes, this.indexPosition);
Debug.Assert(pos == 0);

newRoot.SetPrevPageId(currPage.PageId());
Expand Down Expand Up @@ -538,5 +537,39 @@ public async IAsyncEnumerable<RowHolder> Seek<K>(K seekVal, ITransaction tran)
currPageId = prevPointer;
}
}

private class BTreeUniqueCheckCreator : ColumnTypeHandlerBasicSingle<Action<MixedPage, RowHolder, ITransaction>>
{
public int IndexPosition { get; init; }

public Action<MixedPage, RowHolder, ITransaction> HandleDouble()
{
return (MixedPage page, RowHolder rhToInsert, ITransaction tran) =>
{
double itemToInsertInt = rhToInsert.GetField<double>(this.IndexPosition);
if (page.ElementExists<double>(tran, itemToInsertInt, this.IndexPosition))
{
throw new KeyAlreadyExists();
}
};
}

public Action<MixedPage, RowHolder, ITransaction> HandleInt()
{
return (MixedPage page, RowHolder rhToInsert, ITransaction tran) =>
{
int itemToInsertInt = rhToInsert.GetField<int>(this.IndexPosition);
if (page.ElementExists<int>(tran, itemToInsertInt, this.IndexPosition))
{
throw new KeyAlreadyExists();
}
};
}

public Action<MixedPage, RowHolder, ITransaction> HandleString()
{
throw new NotImplementedException();
}
}
}
}
2 changes: 1 addition & 1 deletion PageManager/PageTypes/IPageSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void ResetDirty()

public abstract void Update(ST item, ushort position, ITransaction transaction);
public abstract int Insert(ST item, ITransaction transaction);
public abstract int InsertOrdered(ST item, ITransaction transaction, ColumnInfo[] columnTypes, Func<RowHolder, RowHolder, int> comparer);
public abstract int InsertOrdered(ST item, ITransaction transaction, ColumnInfo[] columnTypes, int comparisonField);
public abstract void At(ushort position, ITransaction tran, ref ST item);
public abstract void SplitPage(MixedPage newPage, ref RowHolder splitValue, int elemNumForSplit, ITransaction transaction);

Expand Down
14 changes: 12 additions & 2 deletions PageManager/PageTypes/MixedPageType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ public IEnumerable<RowHolder> FetchReverse(ITransaction tran)
}
}

public bool ElementExists<T>(ITransaction tran, T elem, int columnPosition) where T : unmanaged, IComparable
{
tran.VerifyLock(this.pageId, LockManager.LockTypeEnum.Shared);

lock (this.lockObject)
{
return this.items.ElemExists(this.columnTypes, elem, columnPosition);
}
}

public override int Insert(RowHolder item, ITransaction transaction)
{
transaction.VerifyLock(this.pageId, LockManager.LockTypeEnum.Exclusive);
Expand All @@ -123,13 +133,13 @@ public override int Insert(RowHolder item, ITransaction transaction)
}
}

public override int InsertOrdered(RowHolder item, ITransaction transaction, ColumnInfo[] columnTypes, Func<RowHolder, RowHolder, int> comparer)
public override int InsertOrdered(RowHolder item, ITransaction transaction, ColumnInfo[] columnTypes, int comparisonField)
{
transaction.VerifyLock(this.pageId, LockManager.LockTypeEnum.Exclusive);

lock (this.lockObject)
{
int position = this.items.InsertRowOrdered(item, columnTypes, comparer);
int position = this.items.InsertRowOrdered(item, columnTypes, comparisonField);

if (position == -1)
{
Expand Down
2 changes: 1 addition & 1 deletion PageManager/PageTypes/StringOnlyPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ public override void At(ushort position, ITransaction tran, ref char[] item)
throw new NotImplementedException();
}

public override int InsertOrdered(char[] item, ITransaction transaction, ColumnInfo[] columnTypes, Func<RowHolder, RowHolder, int> comparer)
public override int InsertOrdered(char[] item, ITransaction transaction, ColumnInfo[] columnTypes, int comparisonField)
{
throw new NotImplementedException();
}
Expand Down
1 change: 1 addition & 0 deletions PageManager/RowHolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ public override int GetHashCode()
return hash.ToHashCode();
}

// Set of static 0 copy methods.
public static ushort CalculateSizeNeeded(ColumnInfo[] columnInfos)
{
ushort sum = 0;
Expand Down
74 changes: 69 additions & 5 deletions PageManager/RowsetHolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public unsafe struct RowsetHolder

private ushort rowCount;

private static readonly CompareWithRowHolderCreator compareWithRowHolderCreator = new CompareWithRowHolderCreator();

public RowsetHolder(ColumnInfo[] columnTypes, Memory<byte> storage, bool init)
{
System.Diagnostics.Debug.Assert(BitConverter.IsLittleEndian, "Rowset holder fixed assumes that we are running on little endian");
Expand Down Expand Up @@ -106,6 +108,13 @@ public void UpdateRowCount()
}
}

public int CompareFieldWithRowHolder(int row, int col, RowHolder rh, ColumnInfo ci)
{
return ColumnTypeHandlerRouter<Func<int, int, RowHolder, ColumnInfo, RowsetHolder, int>>.Route(
compareWithRowHolderCreator,
ci.ColumnType)(row, col, rh, ci, this);
}

public void GetRow(int row, ref RowHolder rowHolder)
{
System.Diagnostics.Debug.Assert(IsPresent(row));
Expand Down Expand Up @@ -143,9 +152,10 @@ public int InsertRow(RowHolder rowHolder)
}
}

public int InsertRowOrdered(RowHolder rowHolderToInsert, ColumnInfo[] columnTypes, Func<RowHolder, RowHolder, int> comparer)
public int InsertRowOrdered(RowHolder rowHolderToInsert, ColumnInfo[] columnTypes, int comparisonField)
{
// find the first element that is bigger than one to insert.
// No need to keep free items. Try to compact every time.
// TODO: this can be logn.
int positionToInsert = -1;
bool insertAtEnd = false;
Expand All @@ -154,11 +164,8 @@ public int InsertRowOrdered(RowHolder rowHolderToInsert, ColumnInfo[] columnType
{
if (BitArray.IsSet(i, this.storage.Span))
{
RowHolder rowHolder = new RowHolder(columnTypes);
GetRow(i, ref rowHolder);
if (comparer(rowHolderToInsert, rowHolder) != 1)
if (this.CompareFieldWithRowHolder(i, comparisonField, rowHolderToInsert, columnTypes[comparisonField]) != -1)
{
// I am bigger than you, I should be at your place.
positionToInsert = i;
break;
}
Expand Down Expand Up @@ -333,6 +340,33 @@ public IEnumerable<RowHolder> IterateReverse(ColumnInfo[] columnTypes)
}
}

public bool ElemExists<T>(ColumnInfo[] columnTypes, T elem, int columnPos) where T : unmanaged, IComparable
{
ushort colPosition = 0;
for (int i = 0; i < columnPos; i++)
{
colPosition += columnTypes[i].GetSize();
}

for (int i = 0; i < this.maxRowCount; i++)
{
if (BitArray.IsSet(i, this.storage.Span))
{
ushort position = (ushort)(i * this.rowSize + this.dataStartPosition);

fixed (byte* ptr = this.storage.Span)
{
if ((*(T*)(ptr + position + colPosition)).CompareTo(elem) == 0)
{
return true;
}
}
}
}

return false;
}

public ushort MaxRowCount() => this.maxRowCount;

public int FreeSpaceForItems()
Expand Down Expand Up @@ -418,4 +452,34 @@ private int GetTuplePosition(int row, int col)
return tuplePosition + offsetInTouple;
}
}

public class CompareWithRowHolderCreator : ColumnTypeHandlerBasicSingle<Func<int, int, RowHolder, ColumnInfo, RowsetHolder, int>>
{
public Func<int, int, RowHolder, ColumnInfo, RowsetHolder, int> HandleDouble()
{
return (row, col, rh, ci, rs) =>
{
double fieldRowsetHolder = rs.GetRowGeneric<double>(row, col);
double fieldFromRowHolder = rh.GetField<double>(col);
return fieldRowsetHolder.CompareTo(fieldFromRowHolder);
};
}

public Func<int, int, RowHolder, ColumnInfo, RowsetHolder, int> HandleInt()
{
return (row, col, rh, ci, rs) =>
{
int fieldRowsetHolder = rs.GetRowGeneric<int>(row, col);
int fieldFromRowHolder = rh.GetField<int>(col);
return fieldRowsetHolder.CompareTo(fieldFromRowHolder);
};
}

public Func<int, int, RowHolder, ColumnInfo, RowsetHolder, int> HandleString()
{
throw new NotImplementedException();
}
}
}
80 changes: 80 additions & 0 deletions UnitBenchmark/BTreeInsertPerf.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnostics.Windows.Configs;
using DataStructures;
using PageManager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Test.Common;

namespace UnitBenchmark
{
[RPlotExporter]
[EtwProfiler(performExtraBenchmarksRun: true)]
public class BTreeInsertPerf
{
[Params(10_000, 50_000, 100_000, 200_000 /* 500_000, 1_000_000 */)]
public int RowsInTableNumber;

public enum GenerationStrategy
{
Seq,
Rev,
Rand,
FromFile,
}

List<RowHolder> itemsToInsertRand;

ColumnInfo[] schema = new ColumnInfo[]
{
new ColumnInfo(ColumnType.Int)
};

private List<int> GenerateItems(GenerationStrategy strat, int itemNum)
{
switch (strat)
{
case GenerationStrategy.Seq:
return Enumerable.Range(0, itemNum).ToList();
case GenerationStrategy.Rev:
return Enumerable.Range(0, itemNum).Reverse().ToList();
case GenerationStrategy.Rand:
Random rnd = new Random();
return Enumerable.Range(0, itemNum).OrderBy(x => rnd.Next()).Distinct().ToList();
default:
throw new ArgumentException();
}
}

[GlobalSetup]
public void Setup()
{
itemsToInsertRand = GenerateItems(GenerationStrategy.Rand, this.RowsInTableNumber).Select(item =>
{
var row = new RowHolder(schema);
row.SetField(0, item);
return row;
}).ToList();
}

[Benchmark]
public async Task InsertIntoBTreeSingleIntColumnRandomData()
{
var pageManager = new PageManager.PageManager(4096, new FifoEvictionPolicy(10000, 5), TestGlobals.DefaultPersistedStream);
using ITransaction tran = new DummyTran();

Func<RowHolder, RowHolder, int> comp = (rh1, rh2) =>
rh1.GetField<int>(0).CompareTo(rh2.GetField<int>(0));

BTreeCollection collection =
new BTreeCollection(pageManager, this.schema, new DummyTran(), comp, 0);

foreach (var item in this.itemsToInsertRand)
{
await collection.Add(item, tran);
}
}
}
}
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 0889578

Please sign in to comment.