Skip to content

Commit

Permalink
speed up Uint160.CompareTo and Uint256.CompareTo function (#552)
Browse files Browse the repository at this point in the history
* fix zero connect

* speed up  bytes.CompareTo X3 times maybe more.

* Update UInt256.cs

* fix a length error

* make uint benchmarks short,becauce can't pass github test.

* cleanup
  • Loading branch information
lightszero authored and igormcoelho committed Mar 16, 2019
1 parent bc14798 commit a5cd123
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 46 deletions.
45 changes: 19 additions & 26 deletions neo.UnitTests/UT_UIntBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.Cryptography.ECC;
using Neo.IO;
using Neo.Ledger;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Diagnostics;
using System;
//using System.Runtime.CompilerServices.Unsafe;
using System.Diagnostics;

namespace Neo.UnitTests
{
[TestClass]
public class UT_UIntBenchmarks
{
int MAX_TESTS = 1000000; // 1 million
private const int MAX_TESTS = 1000;

byte[][] base_32_1;
byte[][] base_32_2;
Expand All @@ -35,7 +28,7 @@ public void TestSetup()
base_20_1 = new byte[MAX_TESTS][];
base_20_2 = new byte[MAX_TESTS][];

for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
base_32_1[i] = RandomBytes(32);
base_20_1[i] = RandomBytes(20);
Expand All @@ -61,9 +54,9 @@ private byte[] RandomBytes(int count)
return randomBytes;
}

public delegate Object BenchmarkMethod();
public delegate object BenchmarkMethod();

public (TimeSpan, Object) Benchmark(BenchmarkMethod method)
public (TimeSpan, object) Benchmark(BenchmarkMethod method)
{
Stopwatch sw0 = new Stopwatch();
sw0.Start();
Expand All @@ -89,7 +82,7 @@ public void Benchmark_CompareTo_UInt256()
UInt256[] uut_32_1 = new UInt256[MAX_TESTS];
UInt256[] uut_32_2 = new UInt256[MAX_TESTS];

for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
uut_32_1[i] = new UInt256(base_32_1[i]);
uut_32_2[i] = new UInt256(base_32_2[i]);
Expand All @@ -98,7 +91,7 @@ public void Benchmark_CompareTo_UInt256()
var checksum0 = Benchmark(() =>
{
var checksum = 0;
for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
checksum += uut_32_1[i].CompareTo(uut_32_2[i]);
}
Expand All @@ -109,7 +102,7 @@ public void Benchmark_CompareTo_UInt256()
var checksum1 = Benchmark(() =>
{
var checksum = 0;
for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
checksum += code1_UInt256CompareTo(base_32_1[i], base_32_2[i]);
}
Expand All @@ -120,7 +113,7 @@ public void Benchmark_CompareTo_UInt256()
var checksum2 = Benchmark(() =>
{
var checksum = 0;
for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
checksum += code2_UInt256CompareTo(base_32_1[i], base_32_2[i]);
}
Expand All @@ -131,7 +124,7 @@ public void Benchmark_CompareTo_UInt256()
var checksum3 = Benchmark(() =>
{
var checksum = 0;
for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
checksum += code3_UInt256CompareTo(base_32_1[i], base_32_2[i]);
}
Expand All @@ -151,7 +144,7 @@ public void Benchmark_CompareTo_UInt160()
UInt160[] uut_20_1 = new UInt160[MAX_TESTS];
UInt160[] uut_20_2 = new UInt160[MAX_TESTS];

for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
uut_20_1[i] = new UInt160(base_20_1[i]);
uut_20_2[i] = new UInt160(base_20_2[i]);
Expand All @@ -160,7 +153,7 @@ public void Benchmark_CompareTo_UInt160()
var checksum0 = Benchmark(() =>
{
var checksum = 0;
for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
checksum += uut_20_1[i].CompareTo(uut_20_2[i]);
}
Expand All @@ -171,7 +164,7 @@ public void Benchmark_CompareTo_UInt160()
var checksum1 = Benchmark(() =>
{
var checksum = 0;
for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
checksum += code1_UInt160CompareTo(base_20_1[i], base_20_2[i]);
}
Expand All @@ -182,7 +175,7 @@ public void Benchmark_CompareTo_UInt160()
var checksum2 = Benchmark(() =>
{
var checksum = 0;
for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
checksum += code2_UInt160CompareTo(base_20_1[i], base_20_2[i]);
}
Expand All @@ -193,7 +186,7 @@ public void Benchmark_CompareTo_UInt160()
var checksum3 = Benchmark(() =>
{
var checksum = 0;
for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
checksum += code3_UInt160CompareTo(base_20_1[i], base_20_2[i]);
}
Expand All @@ -209,7 +202,7 @@ public void Benchmark_CompareTo_UInt160()
[TestMethod]
public void Benchmark_UInt_IsCorrect_Self_CompareTo()
{
for(var i=0; i<MAX_TESTS; i++)
for (var i = 0; i < MAX_TESTS; i++)
{
code1_UInt160CompareTo(base_20_1[i], base_20_1[i]).Should().Be(0);
code2_UInt160CompareTo(base_20_1[i], base_20_1[i]).Should().Be(0);
Expand Down Expand Up @@ -240,7 +233,7 @@ private unsafe int code2_UInt256CompareTo(byte[] b1, byte[] b2)
{
uint* lpx = (uint*)px;
uint* lpy = (uint*)py;
for (int i = 256/32-1; i >= 0; i--)
for (int i = 256 / 32 - 1; i >= 0; i--)
{
if (lpx[i] > lpy[i])
return 1;
Expand All @@ -257,7 +250,7 @@ private unsafe int code3_UInt256CompareTo(byte[] b1, byte[] b2)
{
ulong* lpx = (ulong*)px;
ulong* lpy = (ulong*)py;
for (int i = 256/64-1; i >= 0; i--)
for (int i = 256 / 64 - 1; i >= 0; i--)
{
if (lpx[i] > lpy[i])
return 1;
Expand Down Expand Up @@ -287,7 +280,7 @@ private unsafe int code2_UInt160CompareTo(byte[] b1, byte[] b2)
{
uint* lpx = (uint*)px;
uint* lpy = (uint*)py;
for (int i = 160/32-1; i >= 0; i--)
for (int i = 160 / 32 - 1; i >= 0; i--)
{
if (lpx[i] > lpy[i])
return 1;
Expand Down
35 changes: 25 additions & 10 deletions neo/UInt160.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,41 @@ public UInt160(byte[] value)
/// Method CompareTo returns 1 if this UInt160 is bigger than other UInt160; -1 if it's smaller; 0 if it's equals
/// Example: assume this is 01ff00ff00ff00ff00ff00ff00ff00ff00ff00a4, this.CompareTo(02ff00ff00ff00ff00ff00ff00ff00ff00ff00a3) returns 1
/// </summary>
public int CompareTo(UInt160 other)
public unsafe int CompareTo(UInt160 other)
{
byte[] x = ToArray();
byte[] y = other.ToArray();
for (int i = x.Length - 1; i >= 0; i--)
fixed (byte* px = ToArray(), py = other.ToArray())
{
if (x[i] > y[i])
return 1;
if (x[i] < y[i])
return -1;
uint* lpx = (uint*)px;
uint* lpy = (uint*)py;
//160 bit / 32 bit step -1
for (int i = (160 / 32 - 1); i >= 0; i--)
{
if (lpx[i] > lpy[i])
return 1;
if (lpx[i] < lpy[i])
return -1;
}
}
return 0;
}

/// <summary>
/// Method Equals returns true if objects are equal, false otherwise
/// </summary>
bool IEquatable<UInt160>.Equals(UInt160 other)
public unsafe bool Equals(UInt160 other)
{
return Equals(other);
fixed (byte* px = ToArray(), py = other.ToArray())
{
uint* lpx = (uint*)px;
uint* lpy = (uint*)py;
//160 bit / 32 bit(uint step) -1
for (int i = (160 / 32 - 1); i >= 0; i--)
{
if (lpx[i] != lpy[i])
return false;
}
}
return true;
}

/// <summary>
Expand Down
35 changes: 25 additions & 10 deletions neo/UInt256.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,41 @@ public UInt256(byte[] value)
/// Method CompareTo returns 1 if this UInt256 is bigger than other UInt256; -1 if it's smaller; 0 if it's equals
/// Example: assume this is 01ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00a4, this.CompareTo(02ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00a3) returns 1
/// </summary>
public int CompareTo(UInt256 other)
public unsafe int CompareTo(UInt256 other)
{
byte[] x = ToArray();
byte[] y = other.ToArray();
for (int i = x.Length - 1; i >= 0; i--)
fixed (byte* px = ToArray(), py = other.ToArray())
{
if (x[i] > y[i])
return 1;
if (x[i] < y[i])
return -1;
ulong* lpx = (ulong*)px;
ulong* lpy = (ulong*)py;
//256bit / 64bit(ulong step) -1
for (int i = (256 / 64 - 1); i >= 0; i--)
{
if (lpx[i] > lpy[i])
return 1;
if (lpx[i] < lpy[i])
return -1;
}
}
return 0;
}

/// <summary>
/// Method Equals returns true if objects are equal, false otherwise
/// </summary>
bool IEquatable<UInt256>.Equals(UInt256 other)
public unsafe bool Equals(UInt256 other)
{
return Equals(other);
fixed (byte* px = ToArray(), py = other.ToArray())
{
ulong* lpx = (ulong*)px;
ulong* lpy = (ulong*)py;
//256bit / 64bit(ulong step) -1
for (int i = (256 / 64 - 1); i >= 0; i--)
{
if (lpx[i] != lpy[i])
return false;
}
}
return true;
}

/// <summary>
Expand Down

0 comments on commit a5cd123

Please sign in to comment.