2015-09-30 8 views
6

मैं एक साधारण समस्या है में फ़ाइलें ढूंढने: मैं इस तरह एक बड़ा और गहरा नेस्टेड निर्देशिका Files.walkFileTree का उपयोग कर संरचना पुनरावृति:कुशलतापूर्वक विशिष्ट निर्देशिका

final int CUTOFF = 5; 
final List<Path> foundList = new ArrayList<>(); 
Files.walkFileTree(codeRoot, new SimpleFileVisitor<Path>() { 
    @Override 
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) 
      throws IOException { 
     String rPath = codeRoot.relativize(dir).toString(); 
     int level = rPath.length() - rPath.replace("/", "").length(); 
     if (dir.getFileName().toString().equals("target") || level < CUTOFF) { 
      return FileVisitResult.CONTINUE; 
     } 
     return FileVisitResult.SKIP_SUBTREE; 
    } 
    @Override 
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 
      throws IOException { 
     if (file.getFileName().toString().endsWith(".txt")) { 
      foundList.add(file); 
     } 
     return FileVisitResult.CONTINUE; 
    } 
}); 

मेरा लक्ष्य एक विशिष्ट निर्देशिका target के तहत सभी फ़ाइलों को जोड़ने के लिए है कि मैं codeRoot के तहत सबसे अधिक CUTOFF स्तरों पर पता है।

मैं आवश्यक stat() कॉल या किसी को "नहीं किया जा सकता" के संदर्भ में ऐसा करने के लिए एक और अधिक प्रभावी तरीका ढूंढ रहा हूं।

भाषा स्तर जावा 8 है।

+0

आपको ऐसा क्यों लगता है कि यह किया जा सकता है? walkFileTree एनआईओ का उपयोग करता है जिसका अर्थ है कि यह प्रदर्शन के संदर्भ में देशी चलने के रूप में उतना ही अच्छा है। यदि आप इसे अक्सर आमंत्रित करते हैं, तो आप कुछ कैश का उपयोग कर सकते हैं। कैश का एक उदाहरण: निर्देशिका के अंतिम संशोधित समय (कुछ फाइल सिस्टम में) निर्देशिका को कैश करने के लिए जो अंतिम कॉल के बाद से नहीं बदला है। –

+0

@MladenAdamovic मैं मुख्य रूप से सोच रहा था कि मुझे कुछ एल्गोरिदमिक शॉर्ट-कट याद आ रही है, क्योंकि मेरा कार्यान्वयन उतना ही बेवकूफ़ है जितना इसे प्राप्त होता है। इसके अलावा, मेरे पास कोई सुराग नहीं है यदि 'relativize()' का प्रदर्शन एफएस प्रदर्शन पर असर पड़ता है जिसे मैं टाल सकता हूं। बार-बार चलाने के अनुकूलन के बारे में आपका विचार एक अच्छा है, धन्यवाद! – mabi

+0

आप अपनी गति के उपाय के रूप में क्या उपयोग कर रहे हैं? क्या आपने संदर्भ बिंदु के रूप में सी/सी ++ में एक समान समाधान लागू किया है? आपको ऐसा क्यों लगता है कि यह अब तक अक्षम है? – Fallso

उत्तर

1

के कारण आप अधिक प्रदर्शन खो नहीं रहे हैं, एल्गोरिदम प्रस्तुत एक बार की क्वेरी है। इस मामले में, आप सभी निर्देशिकाओं के माध्यम से एक रैखिक-समय खोज के साथ फंस गए हैं। आप इस तरह की प्रत्येक निर्देशिका की जांच करने की आवश्यकता को कम नहीं कर सकते हैं। आप निश्चित रूप से कैशिंग को देख सकते हैं, लेकिन यदि आप कैश कोहेरेंसी से परेशान होने जा रहे हैं और उच्च प्रदर्शन की आवश्यकता है तो आप एक इंडेक्स बनाने पर भी विचार कर सकते हैं। किसी भी मामले में मैं आपके द्वारा पूछे गए प्रश्न को संबोधित करूंगा, जो एक बार की क्वेरी के बारे में है।

Files.walkFileTree का संस्करण आप पूरे पेड़ पर चल रहे हैं, जिसमें अधिकतम स्तर से सभी फाइलें और निर्देशिकाएं शामिल हैं। आप पथ नाम को पार्स करके स्पष्ट रूप से उन्हें बाहर कर रहे हैं, एक ऐसी तकनीक जिसे आप सही ढंग से सोचते हैं वह कुशल नहीं हो सकता है। समाधान हमेशा दस्तावेज पढ़ने के लिए है। एक स्पष्ट तर्क के रूप में अधिकतम गहराई के साथ Files.walkFileTree का दूसरा संस्करण है। tutorial on walking the file tree एक से:

दूसरा walkFileTree विधि आप अतिरिक्त दौरा स्तरों की संख्या और FileVisitOption enums का एक सेट पर एक सीमा निर्दिष्ट करने के लिए सक्षम बनाता है।

यदि आप दूसरी विधि का उपयोग करते हैं तो आप केवल अधिकतम स्तर के भीतर उम्मीदवार फ़ाइलों पर जायेंगे, और आप सब कोड से बचने वाले सभी कोड से बच सकते हैं।

+0

अतिरिक्त विधि के बारे में अच्छी पकड़ कैसे ठीक करें। इससे मुझे 'walkFileTree' कार्यान्वयन को देखने के लिए प्रेरित किया गया, जो निर्देशिकाओं का ट्रैक रखने के लिए' स्टैक 'का उपयोग करता है। 'SKIP_SUBTREE' की वापसी स्टैक तत्व को पॉप कर देगी, जो * इस से आगे की ओर होनी चाहिए (इस निर्देशिका के लिए नई स्टैक प्रविष्टियां उत्पन्न नहीं करके) सही है? तो आप कह रहे हैं कि दोनों समकक्ष हैं लेकिन 'maxDepth' संस्करण का उपयोग करके, मैं मैन्युअल गहराई गणना काट सकता हूं? – mabi

+0

@mabi ऑपरेशन जो 'SKIP_SUBTREE' करता है उसे आमतौर पर "छंटनी" कहा जाता है। यह वर्तमान नोड पर ट्रैवर्सल को रोकता है, अपने सभी बच्चों में ट्रैवर्सल से बचाता है, और बस जारी रहता है अगर subtree ट्रैवर्स किया गया था। तो, हाँ, इस व्यवहार का आपका विश्लेषण सही है। दूसरे प्रश्न के लिए, 'maxDepth' का उपयोग करने वाला कार्यान्वयन वास्तव में गहराई का ट्रैक रख रहा है (वास्तव में, यह पहले से ही ऐसा करता है, क्योंकि यह स्टैक का आकार है), इसकी गणना करने की आवश्यकता को कम करता है। युक्ति: कभी भी कोड न लिखें जो किसी और ने आपके लिए पहले ही लिखा है। – eh9

+0

उचित बिंदु। चूंकि आपने "आप और अधिक नहीं कर सकते" और "ऑप्टिमाइज़ेशन के लिए कमरा" बिंदु दोनों को मारा है, इसलिए मैं आपको ईमानदार ईओडी प्रदान करूंगा जब तक कि कोई इससे पहले मेरे दिमाग को उड़ाता न हो। – mabi

1

अनुकूलन विकल्प:

1) अधिसूचना के लिए रजिस्टर जब निर्देशिका परिवर्तन: https://docs.oracle.com/javase/tutorial/essential/io/notification.html इस पृष्ठभूमि

2) (कम इष्टतम) में काम कर सकते हैं (कुछ फ़ाइल सिस्टम में नहीं बदला निर्देशिका की कैशिंग का उपयोग करें): निर्देशिका को कैश करने के लिए निर्देशिका के अंतिम संशोधित समय का उपयोग करें जो अंतिम कॉल

grepcode का उपयोग करके नहीं बदला गया है, मुझे नहीं पता कि कैसे सापेक्ष कार्यान्वित किया गया है, मुझे लगता है कि इसे मूल रूप से कार्यान्वित किया जा सकता है। मुझे लगता है कि इसे पहले से खींचे गए मूल्यों के सरल स्ट्रिंग ऑपरेशंस के साथ कार्यान्वित किया गया है और मुझे नहीं लगता कि यह stat() पर पहुंच रहा है। आप इसका परीक्षण कर सकते हैं हालांकि, relativize के साथ और बिना एक डमी कोड (जो कुछ भी उपयोगी नहीं है) बनाते हैं और बहुत सारी फ़ाइलों को पार करते समय वास्तविक प्रभाव को मापते हैं। आप सुनिश्चित कर सकते हैं कि relativize

+0

'relativize()' JVM + OS निर्भर है, मेरे मामले में यह 'sun.nio.fs.UnixPath' के माध्यम से लागू किया गया है। डिकंपील्ड कोड को ट्रैक करना मुश्किल है। – mabi

+0

एक परीक्षण कोड (जो कुछ भी उपयोगी नहीं करने के साथ निर्देशिका को ट्रैवर्स करता है) के साथ और बिना प्रदर्शन के परीक्षण और परीक्षण के। यदि आपको + 30% कम प्रदर्शन मिलता है जो सापेक्ष है, तो आपको यह समझने की कोशिश करनी चाहिए कि –

संबंधित मुद्दे