如何使此代码更有效?循环和大数据

时间:2016-04-21 18:30:49

标签: java performance hadoop mapreduce analytics

我刚刚学会了几个月前编写代码,但我的项目实际上对我已经知道的非常重,任何有助于提高代码运行效率的帮助都会受到赞赏。

我要做的是让这段代码更有效率,因为需要20个小时才能处理30 MB的文件,我想要处理6.5 GB的文件。我需要它最多30分钟处理文件......可能吗?

我在代码中所做的是

  1. 我提取一个单词并检查它的ID是否存储在我的hashmap中
  2. 我得到了这个词的所有父母,并将它们添加到列表中
  3. 在列表中的每个项目中,我都会获得ID和Word以及其他父母
  4. 我创建一个节点并将其添加到hashmap
  5. 然后继续下一个单词
  6. P.S。我不知道如何做Hadoop MapReduce代码,我知道这是明显的解决方案......但我没有时间去学习它。

    UPDATE !! [正如你在屏幕截图中看到的那样, 99.7%的时间被用于WordNet词典中单词的“getInstance”,这是我正在使用的库:extjWNl。 “getResourceInstance”是调用字典本身的方法,第三个突出显示的条目是调用这些方法的方法(该方法的其余部分实际只花费了0.001%的时间)

    我不确定这个问题是否可以解决,或者你有任何想法吗? - 点击“1”获取屏幕截图] 1

        static HashMap<Long, Node> graph = new HashMap <Long, Node> ();
    
        private static void demonstrateTree (IndexWord word) throws JWNLException {
    
            Long Os = word.getSenses().get(0).getOffset();
    
            if (graph.containsKey(Os)) {
                return;
            }
    
            PointerTargetTree hypernyms = PointerUtils.getHypernymTree(word.getSenses().get(0));
            List<PointerTargetNodeList> hypernymsList = hypernyms.toList();
    
            for(int c=0;c<hypernymsList.size();c++){
    
                PointerTargetNodeList l = hypernymsList.get(c);
    
                for(int j = l.size()-1; j >= 0 ; j--) {
    
                    Long tempid = l.get(j).getPointerTarget().getSynset().getOffset();
                    String tempword = l.get(j).getPointerTarget().getSynset().getWords().get(0).getLemma();
                    Node n = new Node(tempid, tempword, new ArrayList<Node>());
    
                    if (!graph.containsKey(tempid)) {
    
                        n.id = tempid;
                        n.word = tempword;
    
                        if (!(j == l.size()-1)){
                            n.parents.add(graph.get(l.get(j+1).getPointerTarget().getSynset().getOffset()));
                        }
                        graph.put(tempid, n);
                    }       
                }
            }
        }
    
        public static void demonstrateListHelper(String text) throws JWNLException {
    
            String lineText =text.split("\t")[2];
            String [] singleWord = lineText.split("\\s+");
            for (int k=0; k <singleWord.length; k++){
    
                singleWord[k] = singleWord[k].replaceAll("[^\\w]", "");
                IndexWordSet set = Dictionary.getDefaultResourceInstance().lookupAllIndexWords(singleWord[k]);
    
                for (IndexWord word:set.getIndexWordArray()) {
                    demonstrateTree(word);
                }
            }   
        }
    
        public static void generateHierarchy() {
    
            Set<Entry<Long, Node>> iterator = graph.entrySet();
            int i =0;
            for(Entry<Long,Node> e : iterator) {
                System.out.println(i++ +" - " +e.getValue().firstParents());
            }
        }
    
        @SuppressWarnings({ "resource" })
        public static void main(String[] args) throws JWNLException {
            File file = new File("C:/Users/D060891/Desktop/Thesis/sentencesNYT/part-m-00001");
    
            try {
    
                BufferedReader input = new BufferedReader(new FileReader(file));
                String line;
    
                while ((line = input.readLine()) != null) {
                    demonstrateListHelper(line);                              
                }
                generateHierarchy();
            }
    
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    

1 个答案:

答案 0 :(得分:2)

性能优化的第一条规则是不要盯着代码或猜测,而是测量运行时行为。因此,启动一个分析器,看看你的程序在哪里花费时间(或内存)。

一个良好的开端是profile您的代码VisualVM包含在JDK中。

<强>更新 您现在已经确定了瓶颈:

Dictionary.getDefaultResourceInstance()

查看source code每次调用该方法时,都会从XML文档加载一个wordnet字典。因此,只需将瓶颈移出循环并在开头获取字典一次:定义类变量

private static Dictionary dictionary; 

在开头初始化,例如在主要

dictionary = Dictionary.getDefaultResourceInstance();

然后再使用

dictionary.lookupAllIndexWords(singleWord[k]);