2009-12-18 7 views
7

मैं जावा & जॉगएल और सी # & ताओ.ओपेनजीएल के बीच एक बड़ा प्रदर्शन अंतर देख रहा हूं जब दोनों पीएनजी को भंडारण से स्मृति में लोड करते हैं, और लोड करते समय BufferedImage (जावा) या बिटमैप (सी # - दोनों हार्ड ड्राइव पर पीएनजी हैं) 'ओपनजीएल में'।ओपनजीएल प्रदर्शन मुद्दों में पीएनजी लोड हो रहा है - जावा और जॉगएल सी # और ताओ से अधिक धीमी है। ओपनजीएल

यह अंतर काफी बड़ा है, इसलिए मुझे लगता है कि मैं कुछ गलत कर रहा था, हालांकि बहुत सारी खोज और विभिन्न लोडिंग तकनीकों का प्रयास करने के बाद मैं इस अंतर को कम करने में असमर्थ रहा हूं।

जावा के साथ मुझे 248ms में लोड की गई एक छवि मिलती है और 728ms में ओपनजीएल में लोड किया जाता है, सी # पर छवि लोड करने के लिए 54ms लेता है, और 34 मिमी बनावट बनाते हैं।

उपरोक्त प्रश्न में छवि एक पीएनजी है जिसमें पारदर्शिता है, जिसका आकार 7200x255 है, जो 2 डी एनिमेटेड स्प्राइट के लिए उपयोग किया जाता है। मुझे एहसास है कि आकार वास्तव में काफी हास्यास्पद है और स्प्राइट काटने पर विचार कर रहा हूं, हालांकि बड़ा अंतर अभी भी वहां है (और भ्रमित)।

जावा तरफ कोड इस तरह दिखता है:

BufferedImage image = ImageIO.read(new File(fileName)); 
texture = TextureIO.newTexture(image, false); 
texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); 
texture.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); 

सी # कोड का उपयोग करता है:

Bitmap t = new Bitmap(fileName); 

t.RotateFlip(RotateFlipType.RotateNoneFlipY); 
Rectangle r = new Rectangle(0, 0, t.Width, t.Height); 

BitmapData bd = t.LockBits(r, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

Gl.glBindTexture(Gl.GL_TEXTURE_2D, tID); 
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, t.Width, t.Height, 0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, bd.Scan0); 
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR); 
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR); 

t.UnlockBits(bd); 
t.Dispose(); 

के बाद काफी परीक्षण का एक बहुत मैं केवल इस निष्कर्ष पर आ सकता है कि जावा/JOGL यहां बस धीमा है - पीएनजी पढ़ने जितना तेज़ नहीं हो सकता है, या मैं अभी भी कुछ गलत कर रहा हूं।

धन्यवाद।

EDIT2:

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

संपादित 3: 5 भिन्नताओं के लिए बेंचमार्क परिणाम। मैंने एक छोटा बेंचमार्किंग टूल लिखा है, निम्नलिखित परिणाम 33 पीएनजी के सेट को लोड करने से आते हैं, अधिकांश बहुत व्यापक हैं, 5 गुना।

testStart: ImageIO.read(file) -> TextureIO.newTexture(image) 
result: avg = 10250ms, total = 51251 
testStart: ImageIO.read(bis) -> TextureIO.newTexture(image) 
result: avg = 10029ms, total = 50147 
testStart: ImageIO.read(file) -> TextureIO.newTexture(argbImage) 
result: avg = 5343ms, total = 26717 
testStart: ImageIO.read(bis) -> TextureIO.newTexture(argbImage) 
result: avg = 5534ms, total = 27673 
testStart: TextureIO.newTexture(file) 
result: avg = 10395ms, total = 51979 

ImageIO.read (बीआईएस) जेम्स ब्रैनिगन के उत्तर में वर्णित तकनीक को संदर्भित करता है। argbImage तकनीक मेरे पिछले संपादित में वर्णित को दर्शाता है:

img = ImageIO.read(file); 
argbImg = new BufferedImage(img.getWidth(), img.getHeight(), TYPE_INT_ARGB_PRE); 
g = argbImg.createGraphics(); 
g.drawImage(img, 0, 0, null); 
texture = TextureIO.newTexture(argbImg, false); 

लोड हो रहा है के किसी भी अधिक तरीकों (या तो ओपन करने के लिए फ़ाइल से चित्र या छवियाँ) की सराहना की हैं, मैं इन मील के पत्थरों अद्यतन करेगा।

+0

ताओ का उपयोग कर सी # में चलने वाला एक ही बेंचमार्क औसत 11031ms औसत 11031ms लेता है।जावा/जॉगएल के लिए मैंने पाया है कि सबसे तेज विधि से अभी भी 5 गुना तेज है। –

उत्तर

7

संक्षिप्त उत्तर जॉग बनावट वर्ग आवश्यक से थोड़ा अधिक करते हैं, और मुझे लगता है कि यही कारण है कि वे धीमे हैं। मैं कुछ दिनों पहले एक ही समस्या में भाग गया, और अब लो-लेवल एपीआई (glGenTextures, glbindTexture, glTexParameterf, और glTexImage2D) के साथ बनावट को लोड करके इसे ठीक कर दिया। लोडिंग समय लगभग 1 सेकंड से "कोई ध्यान देने योग्य देरी" में कमी नहीं हुई, लेकिन मैंने कोई व्यवस्थित प्रोफाइलिंग नहीं की है।

    :

    लांग उत्तर आप JOGL TextureIO, TextureData और बनावट वर्गों के दस्तावेज और स्रोत कोड में देखें, तो आपको लगता है कि वे सिर्फ GPU पर बनावट अपलोड करने से काफ़ी अधिक करने के नोटिस

  • अलग छवि प्रारूप
  • अल्फा premultiplication

की हैंडलिंग मुझे यकीन है कि जो इनमें से किसी एक अधिक समय लग रहा है नहीं कर रहा हूँ। लेकिन कई मामलों में आप जानते हैं कि आपके पास किस प्रकार का इमेज डेटा उपलब्ध है, और किसी भी प्रील्टिप्लिकेशन की आवश्यकता नहीं है।

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

आखिरकार, निम्न-स्तरीय एपीआई के साथ एक बनावट लोड करना काफी सरल है जब तक कि आपको विभिन्न छवि प्रारूपों को संभालने की आवश्यकता न हो।

val textureIDList = new Array[Int](1) 
gl.glGenTextures(1, textureIDList, 0) 
gl.glBindTexture(GL.GL_TEXTURE_2D, textureIDList(0)) 
gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR) 
gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR) 
val dataBuffer = image.getRaster.getDataBuffer // image is a java.awt.image.BufferedImage (loaded from a PNG file) 
val buffer: Buffer = dataBuffer match { 
    case b: DataBufferByte => ByteBuffer.wrap(b.getData) 
    case _ => null 
} 
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, image.getWidth, image.getHeight, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buffer) 

... 

gl.glDeleteTextures(1, textureIDList, 0) 
+0

हाय, क्या आप bufferedImage से बफर तक पारित होने की बेहतर व्याख्या कर सकते हैं? मैं इसे नहीं प्राप्त कर सकता .. – elect

1

मुझे यकीन नहीं है कि यह प्रदर्शन अंतराल को पूरी तरह से बंद कर देगा, लेकिन आप ImageIO.read विधि का उपयोग करने में सक्षम होना चाहिए जो इनपुटस्ट्रीम लेता है और एक BufferedInputStream में एक FileInputStream को लपेटता है। इससे देशी फ़ाइल I/O कॉल की संख्या को बहुत कम करना चाहिए जो JVM को करना है। यह इस तरह दिखेगा:

 
File file = new File(fileName); 
FileInputStream fis = new FileInputStream(file); 
BufferedInputStream bis = new BufferedInputStream(fis, 8192); //8K reads 
BufferedImage image = ImageIO.read(bis); 
+0

आपकी टिप्पणी के लिए धन्यवाद। बेंचमार्किंग परीक्षणों में मैंने पाया कि यह दृष्टिकोण ImageIO.read (fileName) से भी बदतर है। मैंने अपनी पोस्ट को बेंचमार्क परिणामों और बनावट लोड विविधताओं के साथ संपादित किया है। –

+0

एडवर्ड, बेंचमार्क जानकारी के लिए धन्यवाद। क्या आप एक मध्यम टाइमर भी डाल सकते हैं, ताकि हम ImageIO कॉल और TextureIO कॉल के बीच बिताए गए% को देख सकें? युगल अन्य प्रश्न ... आप किस जेवीएम का उपयोग कर रहे हैं? जेवीएम पर मेमोरी पैरामीटर क्या हैं? क्या आप जेआईटी में या इंटरप्रेटेड मोड में जेवीएम चला रहे हैं? क्या आपने जीसी कॉन्फ़िगर किया है ?, या आप डिफ़ॉल्ट रूप से जीसी चला रहे हैं? आप किस वर्ग प्रोसेसर पर चल रहे हैं? बेंचमार्क के दौरान आपके सिस्टम पर सीपीयू/आईओ के किसी भी अवलोकन? क्या आपका जेवीएम कक्षाओं के एओटी का समर्थन करता है? –

+0

मैं जावा 1.6.0_15 (बी03) चला रहा हूं जिसमें हॉटस्पॉट वीएम के साथ 14.1-बी 022 मिश्रित मोड है, विन 7 64-बिट से (लेकिन 32-बिट डिस्ट फ़ोल्डर चला रहा है)। मैंने जीसी सेटिंग्स को छुआ नहीं है, और यह सुनिश्चित नहीं है कि जेवीएम क्या चल रहा है - डिफ़ॉल्ट सेटिंग्स, "मिश्रित मोड" मुझे लगता है कि कुछ मतलब है लेकिन यह सुनिश्चित नहीं है कि क्या! बेंचमार्किंग के दौरान एक कोर 100% है - यहां अधिक विस्तृत बेंचमार्क परिणाम हैं - http://pastebin.mozilla.org/692710 –

1

आप किसी भी संयोग से JAI (जावा उन्नत इमेजिंग) में देखा है, यह इस तरह png संपीड़ित/विसंपीड़न के रूप में कार्य के लिए देशी त्वरण लागू करता है। पीएनजी डिकंप्रेशन का जावा कार्यान्वयन यहां मुद्दा हो सकता है। आप किस संस्करण का उपयोग कर रहे हैं?

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

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

1

वास्तव में, मैं इस तरह JOGL में मेरी बनावट लोड:

इस तरह से
TextureData data = TextureIO.newTextureData(stream, false, fileFormat); 
Texture2D tex = new Texture2D(...); // contains glTexImage2D 
tex.bind(g); 
tex.uploadData(g, 0, data); // contains glTexSubImage2D 

लोड बनावट एक BufferedImage contructing और यह व्याख्या करने के लिए अतिरिक्त काम बायपास कर सकते हैं। यह मेरे लिए बहुत तेज़ है। यू इसे प्रोफाइल कर सकते हैं। मैं आपके परिणाम की प्रतीक्षा कर रहा हूँ।

0

आप भी एक BufferedImage से सीधे बनावट लोड करने में एक example here है की कोशिश कर सकते हैं: यहाँ कुछ स्केला कोड है जो अपने सभी RGBA बनावट छवियों के लिए अच्छी तरह से काम करता है।

इसका उपयोग करके आप देख सकते हैं कि छवि लोड समय ले रहा है, या बनाएँ/वीडियो मेमोरी के लिए लिखें।

आप छवि के आकार के बारे में भी सोच सकते हैं कि एक पावर 2, यानी 16,32,64,128,256,1024 ... आयाम, कुछ जीएफएक्स कार्ड गैर शक्ति 2 आकारों को संसाधित करने में सक्षम नहीं होंगे, और आप उन जीएफएक्स कार्डों का उपयोग करते समय रिक्त बनावट मिल जाएगी।