2009-12-18 12 views
8

मेरा ऐप एक फ़ाइल सिस्टम का हिस्सा स्कैन करता है, और मेरे उपयोगकर्ताओं ने बताया कि जब वे नेटवर्क ड्राइव स्कैन कर रहे थे तो यह बहुत धीमी थी। मेरे कोड का परीक्षण करते हुए, मैंने बाधा की पहचान की: विधियों File.isFile(), File.isDirectory(), और File.isHidden(), जो सभी fs.getBooleanAttributes(File f) पर कॉल कर रहे हैं। विंडोज नेटवर्क ड्राइव पर यह विधि बहुत धीमी प्रतीत होती है। मैं प्रदर्शन में सुधार कैसे कर सकता हूं? क्या मैं इस विधि को किसी तरह से कॉल करने से बच सकता हूं?फाइल सिस्टम एक्सेस को तेज करना?

उत्तर

6

आप इस फ़ाइल सूची को कैसे बना रहे हैं? जब तक आप एक ही समय में सिस्टम पर प्रत्येक फ़ाइल प्रदर्शित नहीं कर रहे हैं, तो आपके पास कुछ विकल्प हो सकते हैं ...

  1. उपयोगकर्ता द्वारा पूछे जाने पर केवल इस जानकारी को संसाधित करें। जैसे वे फ़ोल्डर "विंडोज" पर क्लिक करते हैं, जिस समय आप विंडोज के भीतर फ़ाइलों को संसाधित कर सकते हैं।
  2. बेहतर प्रतिक्रिया समय के भ्रम को देखते हुए, पृष्ठभूमि थ्रेड में इस जानकारी को संसाधित करें।

शायद यदि आप सूची बनाने के लिए उपयोग कर रहे कोड को दिखाते हैं, तो हम सुधार के कुछ अन्य क्षेत्रों को पा सकते हैं। (आप जानकारी इकट्ठा करने के लिए उपयोग की जाने वाली विधि के आधार पर केवल प्रकार का अनुमान क्यों नहीं लगा सकते हैं? अगर आप गेटफाइल() जैसी विधि को कॉल कर रहे हैं, तो क्या आप पहले से ही नहीं जानते हैं कि लौटाई गई सब कुछ एक फाइल है?)

+0

+1। – wheaties

+0

+2 :) .......... – OscarRyz

+0

आप सही हैं कि मैं आलसी हो सकता हूं और जब उपयोगकर्ता उन्हें पूछता है तो केवल फ़ोल्डरों को लोड कर सकता है, लेकिन फिर उपयोगकर्ता द्वारा खोलने की कोशिश करने पर हर बार एक विराम होगा एक नया फ़ोल्डर, जो पूरे पेड़ को सुस्त महसूस कर सकता है। यह शुरुआत में काफी समय ले रहा है और हर समय धीमा होने के बीच एक व्यापार है ... लेकिन शायद यह इतना बुरा नहीं होगा। मुझे इसका परीक्षण करना होगा। विचारों के लिए धन्यवाद! –

10

रक्षात्मक कोड उन isXYZ() विधियों को अक्सर जारी करता है, और यह आमतौर पर अच्छा अभ्यास होता है। हालांकि, कभी-कभी प्रदर्शन खराब होता है, जैसा आपने पाया है।

एक वैकल्पिक दृष्टिकोण यह मानना ​​है कि फ़ाइल एक फ़ाइल है, यह मौजूद है, यह दृश्यमान, पठनीय, आदि है, और बस कोशिश करें और इसे पढ़ें। यदि यह उन चीजों में नहीं है, तो आपको एक अपवाद मिलेगा, जिसे आप पकड़ सकते हैं, और उसके बाद चेक गलत तरीके से पता लगाने के लिए जांच करें। इस तरह, आप सामान्य मामले (यानी सब ठीक है) के लिए अनुकूलित कर रहे हैं, और चीजें गलत होने पर केवल धीमी परिचालन करते हैं।

+0

हू। समस्या को देखने का यह एक बहुत ही दिलचस्प तरीका है, लेकिन दुर्भाग्यवश यह मेरे मामले में बहुत लागू नहीं है। मैं जो कर रहा हूं वह उपयोगकर्ता की फ़ाइल संरचना को प्रतिबिंबित करने वाला पेड़ बना रहा है, इसलिए मुझे यह पता लगाना होगा कि फ़ाइल एक फ़ाइल या निर्देशिका है या नहीं। हालांकि, मुझे लगता है कि मैं उस भेद को बनाने के लिए listFiles() का उपयोग कर सकता हूं ... धन्यवाद, आपने मुझे कुछ सोचने के लिए दिया है! –

+0

+1 मुझे 'सामान्य मामला' को अनुकूलित करने के बारे में बिंदु पसंद है। फ़ाइल को कुछ नहीं होने पर आप अभी भी रक्षात्मक चेक को संभालने के लिए रख सकते हैं। – mpeterson

+0

+1 मैंने "फ़ाइल" एक निर्देशिका है या नहीं, यह निर्धारित करने के लिए सूचीफाइल का उपयोग करने के लिए मैंने कुछ रिकर्सिव निर्देशिका-वृक्ष प्रसंस्करण कोड को संशोधित किया है; यह स्थानीय और लैन कनेक्टेड ड्राइव के लिए एक मामूली गति है - मैं घर आने तक वीपीएन रिमोट ड्राइव का परीक्षण नहीं कर सकता। यह भी अधिक कॉम्पैक्ट कोड है। –

3

I बिल्कुल एक ही समस्या का सामना करना पड़ा

हमारे मामले का समाधान काफी सरल था: चूंकि हमारी निर्देशिका संरचना एक मानक का पालन कर रही थी (जहां कोई निर्देशिका नहीं थी जिसमें 'नाम' चरित्र था), मैंने बस मानक का पालन किया, और एक बहुत ही सरल ह्युरिस्टिक लागू किया: "हमारे मामले में, निर्देशिका में '।' नहीं है इसके नाम में चरित्र "। यह सरल ह्युरिस्टिक कम से कम हमारे आवेदन को java.io.File क्लास के isDirectory() फ़ंक्शन को कॉल करने की संख्या को कम कर देता है।

शायद यह आपका मामला है। हो सकता है कि आपकी निर्देशिका संरचना पर आप जान सकें कि फ़ाइल सिर्फ नामकरण सम्मेलनों द्वारा निर्देशिका है या नहीं।

+2

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

+0

यह अच्छा होगा अगर मेरे पास उस तरह का मानक निर्भर था, लेकिन दुर्भाग्य से मैं नहीं करता। : ओ) –

2

सूचीफाइल का उपयोग करने के लिए पहले और बाद में कोड उदाहरण है और निर्देशिका पेड़ पर चलने के लिए isDirectory का उपयोग कर रहा है (मेरा कोड प्रत्येक निर्देशिका और फ़ाइल के साथ वास्तव में कुछ करने के लिए सामान्य कॉलबैक का उपयोग करता है; यदि मैं सी # कोडिंग कर रहा था तो यह एक प्रतिनिधि होगा) ।

जैसा कि आप सूची देख सकते हैं फ़ाइल दृष्टिकोण वास्तव में अधिक कॉम्पैक्ट और आसानी से समझा जाता है और साथ ही साथ स्थानीय ड्राइव (950 एमएस बनाम 1000 एमएस), और लैन ड्राइव (26 सेकंड, बनाम 28 सेकंड) पर मामूली तेजी से समझा जा रहा है, दोनों 23 हजार फाइलें

यह बहुत संभव है कि रिमोट कनेक्ट ड्राइव के लिए स्पीडअप पर्याप्त हो सकता है, लेकिन मैं इसे काम से परीक्षण नहीं कर सकता। एक आश्चर्यजनक बात यह है कि विंडोज़ आरएएस वीपीएन में नेटवर्क ड्राइव पर स्पीडअप अभी भी लगभग 10% है।

नए कोड

static public int processDirectory(File dir, Callback cbk, FileSelector sel) { 
    dir=dir.getAbsoluteFile(); 
    return _processDirectory(dir.getParentFile(),dir,new Callback.WithParams(cbk,2),sel); 
    } 

static private int _processDirectory(File par, File fil, Callback.WithParams cbk, FileSelector sel) { 
    File[]        ents=(sel==null ? fil.listFiles() : fil.listFiles(sel)); // listFiles returns null if fil is not a directory 
    int         cnt=1; 

    if(ents!=null) { 
     cbk.invoke(fil,null); 
     for(int xa=0; xa<ents.length; xa++) { cnt+=_processDirectory(fil,ents[xa],cbk,sel); } 
     } 
    else { 
     cbk.invoke(par,fil);             // par can never be null 
     } 
    return cnt; 
    } 

पुराने कोड

static public int oldProcessDirectory(File dir, Callback cbk, FileSelector sel) { 
    dir=dir.getAbsoluteFile(); 
    return _processDirectory(dir,new Callback.WithParams(cbk,2),sel); 
    } 

static private int _processDirectory(File dir, Callback.WithParams cbk, FileSelector sel) { 
    File[]        ents=(sel==null ? dir.listFiles() : dir.listFiles(sel)); 
    int         cnt=1; 

    cbk.invoke(dir,null); 

    if(ents!=null) { 
     for(int xa=0; xa<ents.length; xa++) { 
      File      ent=ents[xa]; 

      if(!ent.isDirectory()) { 
       cbk.invoke(dir,ent); 
       ents[xa]=null; 
       cnt++; 
       } 
      } 
     for(int xa=0; xa<ents.length; xa++) { 
      File      ent=ents[xa]; 

      if(ent!=null) { 
       cnt+=_processDirectory(ent,cbk,sel); 
       } 
      } 
     } 
    return cnt; 
    } 
0

शायद ज़रुरत पड़े तो आप इसे अभी तक प्रयास नहीं किया है, अपने आप को getBooleanAttributes बुला और आवश्यक मास्किंग प्रदर्शन काफी तेज करता है, तो हो सकता है आप एक ही फाइल पर एकाधिक चेक कर रहे हैं। हालांकि एक आदर्श समाधान नहीं है (और वह जो आपके कोड को प्लेटफार्म विशिष्ट होने के लिए धक्का देना शुरू करता है), यह 3 या 4 के कारक द्वारा प्रदर्शन में सुधार कर सकता है। यह एक बहुत ही महत्वपूर्ण प्रदर्शन बढ़ावा है, भले ही यह लगभग उतना तेज़ न हो होना चाहिए।

जेडीके 7 java.nio.file.Path कार्यक्षमता इस तरह की चीज़ को काफी मदद करनी चाहिए।

अंत में, यदि आपके पास अंतिम उपयोगकर्ता वातावरण पर कोई नियंत्रण है, तो सुझाव दें कि आपके उपयोगकर्ता नेटवर्क ड्राइव को स्कैन न करने के लिए अपने एंटीवायरस सॉफ़्टवेयर को कॉन्फ़िगर करते हैं। बड़े एवी समाधानों में से कई (सुनिश्चित नहीं हैं कि वे वास्तव में क्या हल कर रहे हैं) यह डिफ़ॉल्ट रूप से चालू हो गया है। मुझे नहीं पता कि विभिन्न फाइल विधियों पर इसका क्या असर हो सकता है, लेकिन हमने पाया है कि अनुचित रूप से कॉन्फ़िगर किए गए एनीट-वायरस नेटवर्क संसाधनों पर लगभग हर प्रकार की फ़ाइल पहुंच में बड़े विलंबता के मुद्दों का कारण बन सकता है।

+0

यदि मैं getBooleanAttributes() को स्वयं कॉल कर सकता हूं तो यह वास्तव में तेज़ होगा, लेकिन दुर्भाग्य से, मैं जावा 1.5 और जावा.आई.आई.आई.आई.आई.आई.आई.आई.आई.आई. से बाध्य हूं पैकेज-संरक्षित है! मूर्खतापूर्ण अमूर्त बाधा, हर समय रास्ते में हो रही है। : ओ) –

+0

आपको प्रतिबिंब का उपयोग करके विधि पर पहुंचने में सक्षम होना चाहिए (विधि देखें।setAccessible()) एक और चाल जो काम कर सकती है (मुझे यकीन नहीं है कि अगर jvm java.io pacakge में कक्षाओं को अस्वीकार कर देगा यदि वे सूर्य द्वारा हस्ताक्षरित नहीं हैं) तो अपनी खुद की कक्षा बनाना होगा जो एक ही फ़ोल्डर में है (बस इसे अपने जार में java.io फ़ोल्डर में रखें)। –

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