C#-提高搜索时的性能

时间:2018-07-02 15:06:46

标签: c# multithreading performance cryptography text-files

我在txt文件上有一个15000000用户名的列表,我写了一种方法来创建大脑钱包,检查是否有包含600地址列表的地址。就像这样

private static List<string> userList = new List<string>(File.ReadAllLines(@"C:\Users\Erik\Desktop\InfernoUser-workspace-db.txt"));
private static List<string> enterpriseUserList = new List<string>(File.ReadAllLines(@"C:\Users\Erik\Desktop\InfernoEnterpriseUser-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方法将用户名哈希值转换为SHA256字符串,获取其公钥并将其转换为如下地址:

15hDBtLpQfcbrrAFupWjgN5ieHeEBd8mbu

这段代码是屁股,运行速度非常慢,每秒处理大约200行数据。所以我尝试使用多线程对其进行改进

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:\Users\Erik\Desktop\InfernoUser-workspace-db.txt"));
    ParallelOptions check = new ParallelOptions() { MaxDegreeOfParallelism = 100 };
    Parallel.ForEach<string>(items, check, line =>
    {
        CheckAddress(line);
    });
}

没有太大帮助。有人可以建议如何即兴创作吗?与之相比,CPU上运行的vanitygen每秒可处理4-500k地址。怎么有很大的不同?

3 个答案:

答案 0 :(得分:1)

您可以尝试使用具有key = userid的Dictionary,以防止通过列出每次迭代来进行搜索

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]); }
        });

答案 1 :(得分:0)

当寻找效率低下时,主要的红色标志之一是重复的函数调用。您两次致电aggregate。将其放入一个单独的变量中并调用一次应该会有所帮助。

aggregate(other ~ ., df, I)

答案 2 :(得分:0)

您可以在此处执行一些操作

  1. List更新为HashSet。它将大大执行Contains操作。我相信在此代码库中这是最慢的情况。 private static List<string> enterpriseUserList = new List<string>(File.ReadAllLines(@"C:\Users\Erik\Desktop\InfernoEnterpriseUser-local-db.txt")); 改成 private static HashSet<string> enterpriseUserList = new HashSet<string>(File.ReadAllLines(@"C:\Users\Erik\Desktop\InfernoEnterpriseUser-local-db.txt"));
  2. 不要使用ParallelOptions check = new ParallelOptions() { MaxDegreeOfParallelism = 100 };这种优化会提高上下文切换的速度并降低性能。
  3. 使用Parallel.ForEach优化Partitioner.Create

也许这就是我能为您提供的建议。

    private static List<string> userList = new List<string>(File.ReadAllLines(@"C:\Users\Erik\Desktop\InfernoUser-workspace-db.txt"));
    private static HashSet<string> enterpriseUserList = new HashSet<string>(File.ReadAllLines(@"C:\Users\Erik\Desktop\InfernoEnterpriseUser-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])               
     }}

}