C# - Improve performace when searching

Multi tool use
C# - Improve performace when searching
i'm having a list of 15000000 username on txt file & i wrote a method to create brain wallet out of it check if any address contain with a list of 600 address. It's pretty much like this
private static List<string> userList = new List<string>(File.ReadAllLines(@"C:UsersErikDesktopInfernoUser-workspace-db.txt"));
private static List<string> enterpriseUserList = new List<string>(File.ReadAllLines(@"C:UsersErikDesktopInfernoEnterpriseUser-local-db.txt"));
foreach (var i in userList)
{
userid = ToAddress(i);
if (enterpriseUserList.Contains(userid))
Console.WriteLine(i,userid);
{
private string ToAddress(string username)
{
string bitcoinAddress = BitcoinAddress.GetBitcoinAdressEncodedStringFromPublicKey(new PrivateKey(Globals.ProdDumpKeyVersion, new SHA256Managed().ComputeHash(UTF8Encoding.UTF8.GetBytes(username), 0, UTF8Encoding.UTF8.GetBytes(username).Length), false).PublicKey);
}
ToAddrsess method hash username into SHA256 string, get its public key & convert it into address like this:
15hDBtLpQfcbrrAFupWjgN5ieHeEBd8mbu
This code is ass, run really slow, handle about 200 line of data per second. So i try to improve it using multithreading
private static void CheckAddress(string username)
{
var userid = ToAddress(username);
if (enterpriseUserList.Contains(userid))
{
Console.WriteLine(i,userid);
}
}
private static void Parallel()
{
List<string> items = new List<string>(File.ReadLines(@"C:UsersErikDesktopInfernoUser-workspace-db.txt"));
ParallelOptions check = new ParallelOptions() { MaxDegreeOfParallelism = 100 };
Parallel.ForEach<string>(items, check, line =>
{
CheckAddress(line);
});
}
It didn't help much. Can anybody suggest how to improvise this? compare to vanitygen run on CPU which can handle 4-500k address per second. How can it make such a big difference?
Contains
@Bart Friederichs can you be more specific?
– Huang Lee
Jul 2 at 15:21
Instead of encoding the 15 million from user list can you decode the 600 from enterprise list and compare?
– Jimmy
Jul 2 at 15:40
@Jimmy that's not how SHA256 work, you can't reserve it. I selected 600 random username from userList, convert it into address to make enterprise list
– Huang Lee
Jul 2 at 15:43
ok, missed the sha256 part
– Jimmy
Jul 2 at 15:56
3 Answers
3
You can try to use Dictionary with key=userid, to prevent search by list each iteration
var dict = new ConcurrentDictionary<string, string>(100, userList.Count);
userList.AsParallel().ForAll(item =>
{
dict.AddOrUpdate(ToAddress(item), item, (key,value)=>{return value;});
});
enterpriseUserList.AsParallel().ForAll(x =>
{
if (dict.ContainsKey(x))
{ Console.WriteLine(dict[x]); }
});
Thanks, if you have any knowledge about crytocurrency, can you know any mehtod to create brain wallet faster. My code take about 200 milliseconds to create one
– Huang Lee
Jul 2 at 15:30
there're error on AddOrUpdate, it said i can't take 2 arguments. How can i fix this?
– Huang Lee
Jul 2 at 15:45
sure, should be 3 arguments, edited code
– MikkaRin
Jul 2 at 15:50
Second
.AsParallel()
is probably more wasteful than helpful.– Rand Random
Jul 2 at 16:07
.AsParallel()
@HuangLee - not arguing about the first
.AsParallel()
code block witch will give some benefits, but the second wont performe well - the Console.WriteLine
part will synchronize and block the parallel execution - additionally nothing happens there that would need parallel execution. A normal foreach
will perform better. - Depending on the number of calls to Console.WriteLine
you should consider switching to a stringbuilder and call Console.WriteLine(stringBuilder.ToString());
just once.– Rand Random
Jul 2 at 16:18
.AsParallel()
Console.WriteLine
foreach
Console.WriteLine
Console.WriteLine(stringBuilder.ToString());
When looking for inefficiencies one of the major red flags is repeated function calls. You call GetBytes
twice. Putting it into a separate variable and calling it once should help some what.
GetBytes
private string ToAddress(string username)
{
var userNameAsBytes = UTF8Encoding.UTF8.GetBytes(username);
string bitcoinAddress = BitcoinAddress.GetBitcoinAdressEncodedStringFromPublicKey(new PrivateKey(Globals.ProdDumpKeyVersion, new SHA256Managed().ComputeHash(userNameAsBytes, 0, userNameAsBytes.Length), false).PublicKey);
}
i just test it with Stopwatch, it's pretty much the same :|
– Huang Lee
Jul 2 at 15:56
you can perform some operations here
List
HashSet
Contains
private static List<string> enterpriseUserList = new List<string>(File.ReadAllLines(@"C:UsersErikDesktopInfernoEnterpriseUser-local-db.txt"));
private static HashSet<string> enterpriseUserList = new HashSet<string>(File.ReadAllLines(@"C:UsersErikDesktopInfernoEnterpriseUser-local-db.txt"));
ParallelOptions check = new ParallelOptions() { MaxDegreeOfParallelism = 100 };
Parallel.ForEach
Partitioner.Create
maybe that's all I can advise you.
private static List<string> userList = new List<string>(File.ReadAllLines(@"C:UsersErikDesktopInfernoUser-workspace-db.txt"));
private static HashSet<string> enterpriseUserList = new HashSet<string>(File.ReadAllLines(@"C:UsersErikDesktopInfernoEnterpriseUser-local-db.txt"));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void CheckAddress(int id,string username)
{
var userid = ToAddress(username);
if (enterpriseUserList.Contains(userid))
{
// todo
}
}
private static void Parallel()
{
var ranges = Partitioner.Create(0,userList.Count);
Parallel.ForEach(ranges ,(range)=>{
for(int i=range.Item1;i<range.Item2;i++){
CheckAddress(i,userList[i])
}}
}
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Contains
does a linear search, your algorithm basically runs in O(N×M), it would be a lot faster if it could use an index of some sort.– Bart Friederichs
Jul 2 at 15:18