Skip to content

Commit 4e8c81a

Browse files
committed
Fix bug in VectoMultiply. Created Publish profile for publishing release.
1 parent bf97e46 commit 4e8c81a

File tree

12 files changed

+129
-60
lines changed

12 files changed

+129
-60
lines changed

jemalloc.Api/HugeBuffer.cs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ protected override bool ReleaseHandle()
6464

6565
#region Methods
6666
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
67-
public unsafe bool Acquire()
67+
public bool Acquire()
6868
{
6969
if (IsNotAllocated || IsInvalid)
7070
return false;
@@ -164,22 +164,16 @@ public unsafe void VectorMultiply(T value)
164164
{
165165
ThrowIfNotAllocatedOrInvalid();
166166
ThrowIfNotVectorisable();
167-
T[] factor = new T[VectorLength];
168-
for (int f = 0; f < VectorLength; f++)
169-
{
170-
factor[f] = value;
171-
}
172-
Vector<T> factorVector = new Vector<T>(factor);
173167
ThrowIfCannotAcquire();
174168
for (int h = 0; h < segments2.Length; h++)
175169
{
176170
Span<T> span = new Span<T>(segments[h].ToPointer(), segments2[h].Item2);
177-
Span<Vector<T>> vector = span.NonPortableCast<T, Vector<T>>();
178-
int i = 0;
179-
for (i = 0; i < vector.Length; i++)
180-
{
181-
vector[i] = Vector.Multiply(vector[i], factorVector);
182-
}
171+
Span<Vector<T>> vector = span.NonPortableCast<T, Vector<T>>();
172+
T[] fill = new T[VectorLength];
173+
Span<T> sFil = new Span<T>(fill);
174+
sFil.Fill(value);
175+
Vector<T> fillVector = sFil.NonPortableCast<T, Vector<T>>()[0];
176+
vector[0] = Vector.Multiply(vector[0], fillVector);
183177
}
184178
Release();
185179
}
@@ -291,7 +285,7 @@ protected unsafe void AcquirePointer(ref byte* pointer)
291285
}
292286
}
293287

294-
288+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
295289
protected unsafe T Read(ulong index)
296290
{
297291
ThrowIfNotAllocatedOrInvalid();
@@ -434,6 +428,7 @@ private static IndexOutOfRangeException BufferIndexIsOutOfRange(ulong index)
434428
#region Operators
435429
public T this[ulong index]
436430
{
431+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
437432
get => Read(index);
438433

439434
set => Write(index, value);

jemalloc.Api/JemUtil.cs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ public static class JemUtil
1616
public static readonly Type UInt64CLRType = typeof(UInt64);
1717
public static readonly Type SingleCLRType = typeof(Single);
1818
public static readonly Type DoubleCLRType = typeof(Double);
19-
public static readonly Type StringCLRType = typeof(String);
19+
public static readonly Type CharCLRType = typeof(Char);
2020
public static readonly HashSet<Type> NumericTypes = new HashSet<Type>(new Type[]
2121
{
2222
Int8CLRType, UInt8CLRType, Int16CLRType, UInt16CLRType, Int32CLRType, UInt32CLRType, Int64CLRType, UInt64CLRType,
23-
SingleCLRType, DoubleCLRType
23+
SingleCLRType, DoubleCLRType, CharCLRType
2424
});
2525

2626
public static bool IsNumericType<T>()
@@ -51,31 +51,31 @@ public unsafe static TReturn GenericMultiply<TReturn>(TReturn l, TReturn r) wher
5151
switch (value)
5252
{
5353
case Tuple<Byte, Byte> v:
54-
return JemUtil.ValToGenericStruct<Byte, TReturn>((byte) (v.Item1 * v.Item2));
54+
return JemUtil.ValToGenericStruct<Byte, TReturn>(checked((byte) (v.Item1 * v.Item2)));
5555

5656
case Tuple<SByte, SByte> v:
57-
return JemUtil.ValToGenericStruct<SByte, TReturn>((SByte) (v.Item1 * v.Item2));
57+
return JemUtil.ValToGenericStruct<SByte, TReturn>(checked((SByte) (v.Item1 * v.Item2)));
5858

5959
case Tuple<UInt16, UInt16> v:
60-
return JemUtil.ValToGenericStruct<UInt16, TReturn>((UInt16) (v.Item1 * v.Item2));
60+
return JemUtil.ValToGenericStruct<UInt16, TReturn>(checked((UInt16) (v.Item1 * v.Item2)));
6161

6262
case Tuple<Int16, Int16> v:
63-
return JemUtil.ValToGenericStruct<Int16, TReturn>((Int16) (v.Item1 * v.Item2));
63+
return JemUtil.ValToGenericStruct<Int16, TReturn>(checked((Int16) (v.Item1 * v.Item2)));
6464

6565
case Tuple<UInt32, UInt32> v:
66-
return JemUtil.ValToGenericStruct<UInt32, TReturn>((UInt32) (v.Item1 * v.Item2));
66+
return JemUtil.ValToGenericStruct<UInt32, TReturn>((checked(v.Item1 * v.Item2)));
6767

6868
case Tuple<Int32, Int32> v:
69-
return JemUtil.ValToGenericStruct<Int32, TReturn>((Int32)(v.Item1 * v.Item2));
69+
return JemUtil.ValToGenericStruct<Int32, TReturn>((checked(v.Item1 * v.Item2)));
7070

7171
case Tuple<UInt64, UInt64> v:
72-
return JemUtil.ValToGenericStruct<UInt64, TReturn>((UInt64)(v.Item1 * v.Item2));
72+
return JemUtil.ValToGenericStruct<UInt64, TReturn>((checked(v.Item1 * v.Item2)));
7373

7474
case Tuple<Int64, Int64> v:
75-
return JemUtil.ValToGenericStruct<Int64, TReturn>((Int64)(v.Item1 * v.Item2));
75+
return JemUtil.ValToGenericStruct<Int64, TReturn>((checked(v.Item1 * v.Item2)));
7676

7777
default:
78-
return default;
78+
throw new Exception($"Unsupported type: {typeof(TReturn).Name}");
7979
}
8080
}
8181

@@ -88,21 +88,21 @@ public unsafe static double GenericSqrt<TReturn>(TReturn l) where TReturn : stru
8888
switch (l)
8989
{
9090
case SByte v:
91-
return Math.Sqrt(v);
91+
return checked(Math.Sqrt(v));
9292
case Byte v:
93-
return Math.Sqrt(v);
93+
return checked(Math.Sqrt(v));
9494
case Int32 v:
95-
return Math.Sqrt(v);
95+
return checked(Math.Sqrt(v));
9696
case UInt32 v:
97-
return Math.Sqrt(v);
97+
return checked(Math.Sqrt(v));
9898
case Int16 v:
99-
return Math.Sqrt(v);
99+
return checked(Math.Sqrt(v));
100100
case UInt16 v:
101-
return Math.Sqrt(v);
101+
return checked(Math.Sqrt(v));
102102
case Int64 v:
103-
return Math.Sqrt(v);
103+
return checked(Math.Sqrt(v));
104104
case UInt64 v:
105-
return Math.Sqrt(v);
105+
return checked(Math.Sqrt(v));
106106
default:
107107
throw new ArithmeticException();
108108
}

jemalloc.Api/SafeBuffer.cs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ protected override bool ReleaseHandle()
6262

6363
#region Methods
6464
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
65-
public unsafe bool Acquire()
65+
public bool Acquire()
6666
{
6767
if (IsNotAllocated)
6868
return false;
@@ -162,27 +162,21 @@ public Vector<T> AcquireSliceAsVector(int index)
162162
Span<T> span = AcquireSpan().Slice(index, VectorLength);
163163
return span.NonPortableCast<T, Vector<T>>()[0];
164164
}
165-
165+
166+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
166167
public void VectorMultiply(T value)
167168
{
168169
ThrowIfNotAllocatedOrInvalid();
169170
ThrowIfNotVectorisable();
170171
T[] fill = new T[VectorLength];
171-
for (int f = 0; f < VectorLength; f++)
172-
{
173-
fill[f] = value;
174-
}
175-
Vector<T> fillVector = new Vector<T>(fill);
176-
Span <T> span = AcquireSpan();
177-
Span<Vector<T>> vector = span.NonPortableCast<T, Vector<T>>();
178-
for (int i = 0; i < vector.Length; i ++)
179-
{
180-
Vector<T> v = vector[i];
181-
vector[i] = Vector.Multiply(v, fillVector);
182-
}
172+
Span<T> sFil = new Span<T>(fill);
173+
sFil.Fill(value);
174+
Span <Vector<T>> vector = AcquireSpan().NonPortableCast<T, Vector<T>>();
175+
vector[0] = Vector.Multiply(vector[0], sFil.NonPortableCast<T, Vector<T>>()[0]);
183176
Release();
184177
}
185178

179+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
186180
public void VectorSqrt()
187181
{
188182
ThrowIfNotAllocatedOrInvalid();
@@ -214,7 +208,7 @@ protected unsafe virtual IntPtr Allocate(int length)
214208
return handle;
215209
}
216210

217-
protected unsafe void InitVector()
211+
protected void InitVector()
218212
{
219213
if (Length % VectorLength == 0 && SIMD && IsNumeric)
220214
{
@@ -244,6 +238,7 @@ protected unsafe void AcquirePointer(ref byte* pointer)
244238
}
245239
}
246240

241+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
247242
protected unsafe T Read(int index)
248243
{
249244
ThrowIfNotAllocatedOrInvalid();
@@ -383,8 +378,9 @@ private static IndexOutOfRangeException BufferIndexIsOutOfRange(int index)
383378
#endregion
384379

385380
#region Operators
386-
public unsafe T this[int index]
381+
public T this[int index]
387382
{
383+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
388384
get => this.Read(index);
389385

390386
set => this.Write(index, value);

jemalloc.Api/jemalloc.Api.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
99
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1010
<PackageId>jemalloc.NET</PackageId>
11-
<Version>0.1.1</Version>
11+
<Version>0.1.3-alpha</Version>
1212
<Authors>Allister Beharry</Authors>
1313
<Company />
1414
<Product>jemalloc.NET</Product>
15-
<AssemblyVersion>0.1.1.1</AssemblyVersion>
16-
<FileVersion>0.1.1.1</FileVersion>
15+
<AssemblyVersion>0.1.3.1</AssemblyVersion>
16+
<FileVersion>0.1.3.1</FileVersion>
1717
<PackageProjectUrl>https://github.com/allisterb/jemalloc.NET</PackageProjectUrl>
1818
<PackageLicenseUrl>https://github.com/allisterb/jemalloc.NET/LICENSE</PackageLicenseUrl>
1919
<RepositoryUrl>https://github.com/allisterb/jemalloc.NET</RepositoryUrl>

jemalloc.Benchmarks/Benchmarks/NativeVsManagedArray.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ public void GlobalSetup()
2222
}
2323

2424
[BenchmarkCategory("Create")]
25-
[Benchmark(Description = "Create an array on the .NET managed heap", Baseline = true)]
25+
[Benchmark(Description = "Create arrays on the .NET LOH", Baseline = true)]
2626
public void CreateManagedArray()
2727
{
2828
T[] someData = new T[ArraySize];
2929
someData = null;
3030
}
3131

3232
[BenchmarkCategory("Create")]
33-
[Benchmark(Description = "Create a SafeArray on the system unmanaged heap")]
33+
[Benchmark(Description = "Create SafeArrays on the system unmanaged heap")]
3434
public void CreateNativeArray()
3535
{
3636
SafeArray<T> array = new SafeArray<T>(ArraySize);

jemalloc.Benchmarks/Design.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
1-
1. Allocate uint arrays of various sizes from small to very large. Benchmark how long it takes
1+
## Catgeories
2+
3+
1. Malloc: Benchmark low-level malloc operations and creating Span<Y>
4+
5+
2. Arrays: Bench
6+
7+
8+
1. Allocate uint arrays of various sizes from small to very large. Benchmark how long it takes
29
2. Generate random values and assign to random indices of the array. Benchmark.
310
3. Allocate memory and use span
411

512
Things to test:
613

7-
Fragmentation: allocate small and large sizes consecutively.
14+
Fragmentation: allocate small and large sizes consecutively.
15+
16+
LOH stress:
17+
https://www.red-gate.com/simple-talk/dotnet/net-framework/the-dangers-of-the-large-object-heap/
18+
19+
20+
Create an Int32[100000000]; //goes on the LOH
21+
Create an Int32[30000]; //smaller but still big enough to go on the LOH
22+
Throw away the big array but keep the small array. //Creates a 100000000 hole on the LOH immediately followed by an in-use region for the small array.
23+
next iteration will create another big array slightly bigger the first. //This won't fit in the 'hole' of the previous array. The heap must be extended now for the new array to fit.
24+
Loop for a while.
25+
26+
We should find it taking longer and longer to allocate the large arrays and using lots of memory until eventually an OOM happens.
27+
28+
We can do the exact same operations with SafeArray<Int32> and then compare the performance.

jemalloc.Benchmarks/JemBenchmark.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@ public static void SetColdStartOverride(bool value)
3636
JemBenchmarkJobAttribute.ColdStartOverride = value;
3737
}
3838

39+
public static void SetTargetCountOverride(int value)
40+
{
41+
JemBenchmarkJobAttribute.TargetCountOverride = value;
42+
}
43+
44+
public static void SetInvocationCountOverride(int value)
45+
{
46+
JemBenchmarkJobAttribute.InvocationCountOverride = value;
47+
}
48+
49+
public static void SetWarmupCountOverride(int value)
50+
{
51+
JemBenchmarkJobAttribute.WarmupCountOverride = value;
52+
}
53+
3954
public static unsafe TData GetArrayFillValue()
4055
{
4156
TData value = default;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
using BenchmarkDotNet.Attributes;
6+
7+
namespace jemalloc.Benchmarks
8+
{
9+
public class JemBenchmarkAttribute : BenchmarkAttribute
10+
{
11+
}
12+
}

jemalloc.Cli/Program.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ static void Main(string[] args)
5757
.WriteTo.Console(outputTemplate: "{Timestamp:HH:mm:ss}<{ThreadId:d2}> [{Level:u3}] {Message}{NewLine}{Exception}");
5858
L = Log.Logger = LConfig.CreateLogger();
5959
Type[] BenchmarkOptionTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(Options))).ToArray();
60-
ParserResult<object> result = new Parser().ParseArguments<Options, MallocBenchmarkOptions, NativeArrayBenchmarkOptions, HugeNativeArrayBenchmarkOptions>(args);
60+
MethodInfo parseArgumentsMethod = typeof(ParserExtensions).GetMethods().Where(m => m.IsGenericMethod && m.Name == "ParseArguments" && m.GetGenericArguments().Count() == BenchmarkOptionTypes.Count()).First();
61+
Parser p = new Parser();
62+
ParserResult<object> result = (ParserResult<object>) parseArgumentsMethod.MakeGenericMethod(BenchmarkOptionTypes).Invoke(p , new object[] { p, args });
6163
result.WithNotParsed((IEnumerable<Error> errors) =>
6264
{
6365
HelpText help = GetAutoBuiltHelpText(result);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
This file is used by the publish/package process of your project. You can customize the behavior of this process
4+
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
5+
-->
6+
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
7+
<PropertyGroup>
8+
<PublishProtocol>FileSystem</PublishProtocol>
9+
<Configuration>Benchmark</Configuration>
10+
<TargetFramework>netcoreapp2.0</TargetFramework>
11+
<PublishDir>..\x64\Publish</PublishDir>
12+
</PropertyGroup>
13+
</Project>

0 commit comments

Comments
 (0)