2013-02-23 71 views
34

मैं अपने दृश्य में एक बड़ा रास्ता खींच रहा हूं और मैं कुछ प्रदर्शन समस्याओं में भाग रहा हूं। पथ वर्तमान में 32,000 अंक लंबा है, लेकिन मेरा आवेदन कम से कम 128,000 अंक तक स्केल होना चाहिए। मैं वास्तव में पथ के आकार के बारे में कुछ भी नहीं कर सकता, क्योंकि डेटासेट केवल इतना बड़ा है और मुझे पूरे पथ को एक बार में प्रदर्शित करने में सक्षम होना चाहिए और ज़ूम इन करने की आवश्यकता है।ड्राइंग पथ और हार्डवेयर त्वरण

मैं एक नेक्सस 10 का उपयोग कर रहा हूं एंड्रॉइड 4.2 चला रहा है, जिसमें हार्डवेयर त्वरण उन अनुप्रयोगों के लिए डिफ़ॉल्ट रूप से सक्षम है जो इसे स्पष्ट रूप से अक्षम नहीं करते हैं।

dataPath.moveTo(0, offset - (float) data[leftLimit]/ scalingFactor); 
     for (int i = leftLimit; i < rightLimit; ++i) { 
      x = (i - leftLimit) * dx; 
      y = offset - (float) data[i]/ scalingFactor; 
      dataPath.lineTo(x, y); 
     } 

और फिर onDraw() विधि में तैयार:

मार्ग का अनुसरण कोड के साथ बनाई गई है (मैं कुछ सेटअप और अन्य अप्रासंगिक भागों छोड़े गए)

canvas.drawColor(Color.WHITE); 
canvas.drawPath(dataPath, linePaint); 

मैं समय मापा यह हार्डवेयर त्वरण के साथ और बिना adb shell dumpsys gfxinfo का उपयोग करके अपना विचार खींचने के लिए लेता है, और मेरे आश्चर्य के लिए हार्डवेयर त्वरण बहुत धीमा है:

हार्डवेयर त्वरण के साथ:

enter image description here

हार्डवेयर त्वरण के बिना:

enter image description here

हार्डवेयर त्वरित संस्करण फ्रेम प्रति चारों ओर 200-300 एमएस, सबसे प्रक्रिया चरण में खर्च लेता है। गैर-त्वरित संस्करण लगभग 50 एमएस लेता है, ड्रा चरण में 2/3 और प्रक्रिया चरण में 1/3।

स्पष्ट रूप से हार्डवेयर त्वरण के बिना भी मेरा तेज संस्करण 60 एफपीएस प्राप्त करने में अभी भी धीमा है, या जब मैं बड़े डेटासेट में जाता हूं तो भी मुश्किल से उपयोग करने योग्य होता है।

बिटमैप के पथ को प्रस्तुत करने का विचार और फिर स्क्रीन को फिट करने के लिए केवल उस बिटमैप को बदलने के लिए मेरे मामले में समस्याग्रस्त भी है। मुझे पथ पर बहुत दूर ज़ूमिंग का समर्थन करने की आवश्यकता है, और पथ की गुणवत्ता के बिना ज़ूमिंग को और भी बदतर करने में सक्षम होने के लिए मुझे पथ के बड़े आकार के बिटमैप्स प्रस्तुत करना होगा (और संभवतः स्मृति सीमाओं और बनावट आकार सीमाओं में भाग लेना होगा)। और जब तक ज़ूमिंग करना है तो मुझे या तो पथ के केवल हिस्सों की नई छवियां बनाना होगा, या सीधे पथ को सीधे प्रस्तुत करने के लिए स्विच करना होगा, जो संभवतः फ़्रेमेट से अधिक देरी का कारण बन जाएगा यदि प्रदर्शन अभी भी मेरे पास सही है अभी व।

क्या मैं अब सोच रहा हूँ

  • आ रहा है लाइनों/रास्तों बस कुछ GPU में बुरा है और है कि एक हार्डवेयर के लिए कोशिश नहीं करनी चाहिए तेजी लाने, या मैं कुछ गलत होने की संभावना है कि बुरा का कारण बनता है कर रहा हूँ है प्रदर्शन?
  • क्या स्वीकार्य प्रदर्शन के साथ ऐसे विशाल पथ खींचने के लिए मैं कुछ भी कर सकता हूं?
+0

ओपनजीएल इस में कैसे ठीक है? –

+0

हार्डवेयर त्वरण ओपनजीएल का उपयोग करता है, जहां तक ​​मैं इसे समझता हूं। लेकिन मुझे यकीन नहीं था कि किस टैग का उपयोग करना है। –

+1

आप इसे कैसे आकर्षित कर रहे हैं? यदि आप GPU के लिए एक समय में 1 बिंदु प्लॉट करते हैं तो आपको शायद खराब प्रदर्शन मिलेगा, लेकिन यदि आप इसे सभी पर बैच करते हैं तो आपको कम से कम सिद्धांत में वृद्धि दिखाई देनी चाहिए। – Automatico

उत्तर

44

आ रहा है लाइनों/रास्तों बस कुछ GPU पर और है कि बुरा है एक हार्डवेयर तेजी लाने के लिए कोशिश नहीं करनी चाहिए, या मैं संभावना कुछ कर रहा हूँ गलत है कि खराब प्रदर्शन का कारण बनता है?

पथ हमेशा CPU का उपयोग करके प्रस्तुत किए जाते हैं। जब ऐप हार्डवेयर तेज हो जाता है तो इसका मतलब है कि रेंडरर पहले सीपीयू का उपयोग करके बिटमैप में अपना रास्ता खींच लेगा, फिर उस बिटमैप को जीपीयू में बनावट के रूप में अपलोड करें और अंततः स्क्रीन पर बनावट खींचें।

लाइन्स पूरी तरह हार्डवेयर त्वरित हैं। Path का उपयोग करने के बजाय मैं आपको इस मामले में Canvas.drawLines() का उपयोग करने की सलाह देता हूं।

क्या स्वीकार्य प्रदर्शन के साथ ऐसे विशाल पथ खींचने के लिए मैं कुछ भी कर सकता हूं?

आपको या तो Canvas.drawLines() का उपयोग करना चाहिए या अपने आप को प्रबंधित करने वाले Bitmap में पथ प्रस्तुत करना चाहिए।

+2

ड्राइंग पथ मैन्युअल रूप से 'बिटमैप' में और स्क्रीन पर उन्हें स्थानांतरित करने की अनुमति देने के लिए, मैंने सरल कोड [यहां] (https://github.com/barthand/android-pathbitmap) को धक्का दिया। मैंने जीपीयू-त्वरित नक्शा व्यू पर ओवरले के रूप में इस तरह के पथों को आकर्षित करने के लिए एक ही तकनीक का उपयोग किया (जहां ओवरले पर पथ खींचने की सामान्य जीपीयू-त्वरित विधि 'बनावट के कारण' बनावट के रूप में बहुत बड़ा आकार 'त्रुटि उत्पन्न कर रही थी जीपीयू पर आकार सीमा)। – barthand

+0

मेरे लिए, 'कैनवास.drawLines (फ्लोट [], पेंट) का उपयोग करके बिंदुओं के एक बैच के साथ, एकल बिंदु के साथ' Canvas.drawLine (int int int, int, int) 'के लिए कई कॉलों की बजाय, प्रदर्शन में काफी वृद्धि हुई । – Robert

+0

क्या कोई आधिकारिक साइट या दस्तावेज़ है जो बताता है कि पथ CPU का उपयोग करता है और 'Canvas.drawLines()' हार्डवेयर त्वरण का उपयोग करता है? मैं यह पूछ रहा हूं क्योंकि मेरे पास बहुत खराब प्रदर्शन था, प्रदर्शन युक्तियों की खोज की लेकिन मुझे कुछ अर्थपूर्ण नहीं मिला, जब तक कि मैं यह जवाब नहीं पढ़ता। – Robert

5

ऐसा लगता है कि आप GPU में सामान्य बाधा में चल रहे हैं।

How to make route drawing more efficient

Android canvas path real time performance

Switching from canvas to OpenGL

विशेष रूप से पहले एक है, जो सुझाव है कि आप एक बिटमैप बनाने के लिए और है कि बजाय आकर्षित: निम्न लिंक पर एक नज़र डालें। ऐसा लगता है कि अगर आप ओपनजीएल में बदल जाते हैं तो आप कुछ बेहतर प्रदर्शन प्राप्त कर सकते हैं। काम करने के लिए मौजूदा विधि प्राप्त करने का कुछ जादू तरीका हो सकता है, लेकिन मुझे इस समय इस बारे में पता नहीं है।

आप जो व्यवहार कर रहे हैं उसे क्यों देख रहे हैं शायद इसलिए कि आप प्रत्येक ड्रॉ के बीच GPU को सभी डेटा भेजते हैं। आपको इसे GPU पर कैश करना चाहिए और स्थिरता में अनुवाद का उपयोग करना चाहिए। डेटा को पुन: प्रयास नहीं करना और इसे सभी GPU को भेजना। आप शायद I/O bound हैं, जिसका अर्थ है कि सीपीयू और जीपीयू के बीच संचरण दर आपके प्रदर्शन को सीमित कर रही है। आपके द्वारा प्रदान किए गए डेटा के आधार पर मैं 100% सुनिश्चित नहीं हो सकता, लेकिन यह मेरा सबसे अच्छा अनुमान है। विभिन्न कैशिंग तकनीकों का प्रयास करें, मुख्य रूप से लिंक # 1 से पीएनजी-कैश।

3

पथ खींचने से लाइनों को आकर्षित करने के लिए जीपीयू को "कहने" से अधिक शामिल होगा। पथ में कई विशेषताएं होती हैं, उदाहरण के लिए लाइनों के सिरों का इलाज कैसे किया जाता है या एक रेखा बिंदी जाती है, GPU त्वरित नहीं है। शायद अन्य हिकअप है जब आप कई लाइनों का सामना करते हैं जो सीपीयू और जीपीयू त्वरण के संयोजन को धीमा कर देते हैं। canvs.drawPath के बजाय canvas.drawLines पर जाने के लिए उपरोक्त सुझाया गया समाधान और एक फैंसी Paint विधि का उपयोग करने में सहायता करने का प्रयास करने में सहायता करें।

यदि यह मदद नहीं करता है तो आप GLSurfaceView का उपयोग करने और इसके बजाय सीधे लाइनों को प्रस्तुत करने का प्रयास कर सकते हैं। इसमें कुछ ओपनजीएल ईएस ज्ञान शामिल होगा, लेकिन ऐसा करने के लिए अविश्वसनीय रूप से कठिन नहीं होना चाहिए और यह बहुत अधिक प्रभावी हो सकता है।

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

  • कोई संबंधित समस्या नहीं^_^