C#程序运行缓慢

时间:2014-06-29 11:00:16

标签: c# lucene

我在C#中有一个程序,其psuedocode看起来像这样。程序运行正常,但需要5天才能运行。我需要每天运行这个新标准。 我们正在尝试标记生物学书籍中的每个花卉名称。每天它都是.txt格式的不同教科书或期刊。我们正在使用Lucene搜索来加快速度。我们在数据库中有FLowerFamilyID列表。我们还有FlowerID | FlowerCommon名称在csv文件中。这个csv文件有大约10,000个条目。

步骤1 //从SQL服务器获取FlowerFamilyID&转储文本文件。这有大约100个条目

FlowerFamilyID FamilyName 
1             Acanthaceae
2                 Agavaceae

步骤2 // csvfile有flowerid,flowercommonname。读取csv文件(大约10000个条目)并将它们存储在列表中,例如:

1|Rose   
2|American water willow 
3|false aloe

步骤3 //当天在Book / Journal上创建Lucene索引

步骤4 //为来自datatextfile的每个familyflowerID调用SearchFlower(flowerfamilyID,花卉列表)。返回在该书/期刊中找到的所有花朵

步骤5 //在搜索功能中,我调用Lucene查询解析器&搜索10000个鲜花条目,如果找到,则在列表中存储第一个得分

        public static List<flowerResult> searchText(String flowerfamilyid, List<flower> flowers)
    {
        DateTime startdate = DateTime.Now;   
        List<flowerResult> results = new List<flowerResult>();
        Document doc = new Document();   

        foreach (var flower in flowers)
        {           
            string[] separators = { ",", ".", "!", "?", ";", ":", " " };
            string value = flower.getFlower().Trim().ToLower();
            string[] words = value.Split(separators, StringSplitOptions.RemoveEmptyEntries);
             String criteria = string.Empty;
            if (words.Length > 1)
                criteria = "\"" + value+ "\"";
            else
                criteria = value;

            if (string.IsNullOrEmpty(criteria))
                continue;
            criteria = criteria.Replace("\r", " ");
            criteria = criteria.Replace("\n", " ");

            QueryParser queryParser = new QueryParser(VERSION, "body", analyzer);
            string special = " +body:" + criteria;
            Query query = queryParser.Parse(special);      
            try
            {      
                IndexReader reader = IndexReader.Open(luceneIndexDirectory, true);
                Searcher indexSearch = new IndexSearcher(reader);
                TopDocs hits = indexSearch.Search(query, 1);
                if (hits.TotalHits > 0)
                {
                    float score = hits.ScoreDocs[0].Score;
                    if (score > MINSCORE)
                    {
              flowerResult result = new flowerResult(flower.getId(), flower.getFlower(), score);
                        results.Add(result);
                    }
                }      
                indexSearch.Dispose();
                reader.Dispose();
                indexWriter.Dispose();
            }
            catch (ParseException e)
            {//"Could not parse article. Details: " + e.Message);
              }
        }

        return results;
    }

public class flower
{
    public long flowerID {get;set;}
    public string familyname {get;set;}
    public string flower {get;set;} //common name
}

我试过这个,&amp;它在5天内完成。但我需要在一天之内完成这项工作,bcoz结果用于进一步分析。因此,我将csv文件拆分为10个不同的文件和作业 在2天内完成。团队负责人告诉我使用多个线程来提高速度。我不知道该怎么做。有人可以帮帮我吗?

由于 [R

1 个答案:

答案 0 :(得分:-1)

我之前遇到过类似的问题,并且发现foreach通常是个问题。在这里,您将迭代10000个条目的列表。虽然这本身不是问题,但你没有说过花类的样子。它只是几个字符串?

现在,当你处理一个foreach并且foreach正在迭代一个类时,你实际做的是创建一个类的实例,将类的指向对象复制到新实例中并对其进行处理。例如,您的课程可能看起来像这样

public class flower
{
    public string genus {get;set;}
    public string colour {get;set;}
    public int occurrences {get;set;}
    public int page {get;set;}
    public int chapter {get;set;}
    public string commonName {get;set;}
}

然后你有一个10000的列表。

每次有foreach时,都有

foreach(Flowers myFlower in flowers)

这会为每次花的迭代创建一个Flowers实例

然后你在花上执行某种字符串操作(我不知道getFlower是做什么的,但我会假设它返回一个字符串)。

接下来检查字符串是否为null或为空,如果还执行其他搜索,则继续。虽然搜索速度很慢,但最终不需要.Dispose(一旦你超出范围,实例就会被销毁,GC会做它所需要的)

我怎么做才是只在花卉清单中的任何需要使用的东西上操作foreach而不是其他任何东西。也可以重构查询,以便在循环内每次执行实例化而不是每次执行。我发现的另一个技巧是尽可能使用LINQ。您还要创建10000倍的分隔符字符串 - 将其带到循环外部。

if (words.Length > 1)
            criteria = "\"" + value+ "\"";
        else
            criteria = value;

可以改写为

criterial = words.Length > 1 ? "\"" + value+ "\"" : value;

flowerResult result = new flowerResult(flower.getId(), flower.getFlower(), score);
results.Add(result);

可以合并为一行(避免必须创建新变量)

results.Add(flower.getId(), flower.getFlower(), score);

这里你也是第二次在相同的处理数据上调用getFlower - 我认为你使用value作为变量名。请记住,每次调用外部方法时,事情都会变慢

这些都是基于你放在这里的所有假设。

另一件要尝试的是不使用强类型名称。例如

IndexReader reader = IndexReader.Open(luceneIndexDirectory, true);
Searcher indexSearch = new IndexSearcher(reader);
TopDocs hits = indexSearch.Search(query, 1);

都很好,但是当我使用.NET 4运行测试时,var形式会更快,具体取决于你的工作。因此,试试

var reader = IndexReader.Open(luceneIndexDirectory, true);
var indexSearch = new IndexSearcher(reader);
var hits = indexSearch.Search(query, 1);

我发现它们变慢的唯一一次是你使用原语(比如int,double和bool)

小事情,但它们可能会加快速度。