2011-04-30 8 views
7

के साथ छवि लोडिंग प्रदर्शन समस्याएं मेरे पास एक जीटीके (गोब्जेक्ट) इंटरफेस के साथ एक स्क्रिप्ट है जिसका उपयोग मैं अपने फोटो ब्लॉग पर पोस्ट करने के लिए करता हूं।पाइथन और गोबजेक्ट

मैं पृष्ठभूमि थ्रेड में छवियों को लोड करके इसकी प्रतिक्रिया में सुधार करने की कोशिश कर रहा हूं।

मुझे पृष्ठभूमि थ्रेड से GdkPixbuf ऑब्जेक्ट्स को पॉप्युलेट करने की कोशिश करने की कोई किस्मत नहीं है, मैंने जो कुछ भी कोशिश की है, वह सिर्फ जम्मू ठोस है।

तो एक वैकल्पिक के रूप में मैंने सोचा कि मैं पृष्ठभूमि धागे में फ़ाइलों को पढ़ूंगा और फिर उन्हें GdkPixbuf की मांग पर धक्का दूंगा। इस दृष्टिकोण ने कुछ आश्चर्यजनक और निराशाजनक प्रदर्शन परिणामों को जन्म दिया है जो मुझे आश्चर्यचकित करते हैं कि मैं कुछ गलत कर रहा हूं।

मैं अपने कैमरे से हल्के से संकुचित जेपीईजी के साथ खेल रहा हूं, वे लगभग 3.8 एमबी होते हैं।

यहाँ मूल अवरुद्ध छवि लोड है:

pb = GdkPixbuf.Pixbuf.new_from_file(image_file) 

यह औसत के बारे में 550ms, विशाल, बल्कि थकाऊ यदि आप एक दर्जन से अधिक चित्रों के माध्यम से झटका करना चाहते हैं।

तो मैं उसे विभाजित करें, यहाँ फ़ाइल को पढ़ने के लिए:

data = bytearray(open(self.image_file).read()) 

यह औसत 15ms, कि, वास्तव में अच्छा, लेकिन यह भी थोड़े चिंता है कि अगर हम 15ms में फ़ाइल पढ़ सकते हैं अन्य 535ms खर्च किया जा रहा हैं क्या पर?

संयोग से बाइटियर कॉल मौजूद है क्योंकि PixBufLoader अन्यथा डेटा स्वीकार नहीं करेगा।

और फिर जरूर लोड:

pbl = GdkPixbuf.PixbufLoader() 
pbl.write(data, len(data)) 
pbl.close() 
pb = pbl.get_pixbuf() 

1400ms के आसपास यह औसत है, जो लगभग 3 बार जीटीके यह सब करने दे अधिक लंबी है।

क्या मैं यहां कुछ गलत कर रहा हूं?

+2

आप अजगर रूपरेखा उपकरण का उपयोग कर देखने के लिए जहां समय खर्च किया जाता है माना जाता है:

यहाँ स्रोत है? –

+0

पिक्सबफलोडर क्लोज कॉल वर्तमान में मेरे रनटाइम का 9 4% है, मुझे उस कॉल के अंदर कोई विवरण नहीं मिलता है। –

उत्तर

2

मेरा अनुमान है: आप कुछ गलत कर रहे हैं। मैंने libdpeg-turbo की तुलना gdk.PixbufLoader से की है और लगभग कोई गति अंतर नहीं मिला है। मेरे द्वारा उपयोग किया गया कोड नीचे है।

libjpeg-टर्बो के लिए (jpegload.c):

#include <assert.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/time.h> 

#include <jpeglib.h> 

void decompress(FILE* fd) 
{ 
    JSAMPARRAY buffer; 
    int row_stride; 
    struct jpeg_decompress_struct cinfo; 
    struct jpeg_error_mgr jerr; 
    cinfo.err = jpeg_std_error(&jerr); 
    jpeg_create_decompress(&cinfo); 
    jpeg_stdio_src(&cinfo, fd); 
    jpeg_read_header(&cinfo, TRUE); 
    jpeg_start_decompress(&cinfo); 
    row_stride = cinfo.output_width * cinfo.output_components; 
    buffer = (*cinfo.mem->alloc_sarray) 
       ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); 
    while (cinfo.output_scanline < cinfo.output_height) { 
    (void) jpeg_read_scanlines(&cinfo, buffer, 1); 
    } 
    jpeg_finish_decompress(&cinfo); 
    jpeg_destroy_decompress(&cinfo); 
} 

int main(int argc, char** argv) 
{ 
    long len; 
    FILE *fd; 
    unsigned char *buf; 
    struct timeval start, end; 
    int i; 
    const int N = 100; 
    int delta; 

    /* read file to cache it in memory */ 
    assert(argc == 2); 
    fd = fopen(argv[1], "rb"); 
    fseek(fd, 0, SEEK_END); 
    len = ftell(fd); 
    rewind(fd); 
    buf = malloc(len); 
    assert(buf != NULL); 
    assert(fread(buf, 1, len, fd) == len); 

    gettimeofday(&start, NULL); 
    for(i = 0; i < N; i++) { 
    rewind(fd); 
    decompress(fd); 
    } 
    gettimeofday(&end, NULL); 
    if(end.tv_sec > start.tv_sec) { 
    delta = (end.tv_sec - start.tv_sec - 1) * 1000; 
    end.tv_usec += 1000000; 
    } 
    delta += (end.tv_usec - start.tv_usec)/1000; 
    printf("time spent in decompression: %d msec\n", 
     delta/N); 
} 

अजगर को जरूर लिए (gdk_load.py):

import sys 
import gtk 
import time 

def decompress(data): 
    pbl = gtk.gdk.PixbufLoader() 
    pbl.write(data, len(data)) 
    pbl.close() 
    return pbl.get_pixbuf() 

data = open(sys.argv[1]).read() 

N = 100 
start = time.time() 
for i in xrange(N): 
    decompress(data) 
end = time.time() 
print "time spent in decompression: %d msec" % int((end - start) * 1000/N) 

टेस्ट रन परिणाम:

$ gcc jpegload.c -ljpeg 
$ ./a.out DSC_8450.JPG 
time spent in decompression: 75 msec 
$ python gdk_load.py DSC_8450.JPG 
time spent in decompression: 75 msec 
$ identify DSC_8450.JPG 
DSC_8450.JPG JPEG 3008x2000 3008x2000+0+0 8-bit DirectClass 2.626MB 0.000u 0:00.019 

संपादित करें : और एक और परीक्षण, gi.repostiroy का उपयोग करके इस बार:

import sys 
import time 
from gi.repository import GdkPixbuf 

def decompress(filename): 
    pb = GdkPixbuf.Pixbuf.new_from_file(filename) 
    return pb 

N = 100 
start = time.time() 
for i in xrange(N): 
    decompress(sys.argv[1]) 
end = time.time() 
print "time spent in decompression: %d msec" % int((end - start) * 1000/N) 

और परिणाम:

$ python gi_load.py DSC_8450.JPG 
time spent in decompression: 74 msec 

gi.repository का उपयोग कर GdkPixbuf.PixbufLoader वास्तव में बहुत ज्यादा तो "शुद्ध" gtk.gdk धीमी है।कोड:

import sys 
import time 
from gi.repository import GdkPixbuf 

def decompress(data): 
    pbl = GdkPixbuf.PixbufLoader() 
    pbl.write(data, len(data)) 
    pbl.close() 
    return pbl.get_pixbuf() 

data = bytearray(open(sys.argv[1]).read()) 

N = 100 
start = time.time() 
for i in xrange(N): 
    decompress(data) 
end = time.time() 
print "time spent in decompression: %d msec" % int((end - start) * 1000/N) 

परिणाम:

$ python gi_load.py DSC_8450.JPG 
time spent in decompression: 412 msec 

लेकिन GdkPixbuf.Pixbuf.new_from_file के रूप में तेजी से के रूप में शुद्ध सी संस्करण भी gi.repository उपयोग कर काम करता है, तो आप अभी भी या तो कुछ गलत कर रहे हैं, या बहुत ज्यादा की उम्मीद कर।

+0

फाइल से पढ़ने के रूप में डेटा पास करने के गोब्जेक्ट के तहत काम नहीं किया गया है, इसलिए बाइटियर कॉल की आवश्यकता है, मुझे आश्चर्य है कि यह समस्या का स्रोत है या नहीं। –

+0

"गोब्जेक्ट के तहत" का क्या मतलब है? क्या आप फ़ाइलों को पढ़ने के लिए gobject I/O कोड का उपयोग कर रहे हैं? – abbot

+0

gtk आयात करने के बजाय मैं gi.repository से जीटीके आयात कर रहा हूं, जाहिर है यह "नया गोब्जेक्ट" तरीका है, pygtk साइट इसे नए कोड के लिए अनुशंसा करती है, व्यावहारिक रूप से इसका मतलब यह है कि सबकुछ उन pygtk उदाहरणों से अलग है जो मुझे मिलते हैं वेब। –

1

मैंने pygtk के साथ एक छोटा छवि दर्शक विकसित किया है। मैं पिक्सबफलोडर का उपयोग करता हूं, लेकिन मैं प्रति एन केवल बाइट्स लिखता हूं()। Idle_add() के साथ संयोजन में मैं पृष्ठभूमि में एक छवि लोड कर सकता हूं, जबकि एप्लिकेशन अभी भी उपयोगकर्ता इनपुट पर प्रतिक्रिया देता है। http://guettli.sourceforge.net/gthumpy/src/ImageCache.py

+0

यह दिलचस्प है, वर्तमान में मैं pixbufloader के करीबी कॉल पर एक बड़ी (2 सेकंड) देरी का अनुभव करता हूं। दुर्भाग्य से मैं यह देखने के लिए आपका नहीं मिल सका कि क्या यह एक समान मुद्दा है। –