Re: psyco

Pierre-Frédéric Caillaud <[email protected]>
Newsgroups gmane.comp.web.skunkweb
Organization La Boutique Numérique
Message-ID <opsarw1ji3cq72hf@musicbox>
	Okay, so let's go.

	Comments on STML compilation :

	***************************************
	* Problem :
	In Python, Global variables are slow, and locals are fast. I see all stml  
compiled code is put straight into the top level of a code object. I don't  
know if this behaves like a function or like a module, but the variables  
are probably considered global (thus slow). Besides, Psyco does not  
accelerate code in the top level of a module.

	***************************************
	Proposed solution :
	Generate functions instead of modules.
	Calling a component looks a lot like a function call anyway ; why not  
make it a function call ? You could use **kwargs for parameter passing,  
etc. The important part is that all code in a component should be in a  
function to make the variables local. Besides, the component namespace is  
not connected to the caller's namespace, so a function is suitable.

	For include's, it could be a little more difficult to implement, but that  
is not really a problem ; the components are where most of the processing  
time is spent.

	***************************************
	Here is an example program :
	It just increments a variable 1000.000 times.

import time
import psyco

test_len = 1000000

# test globals
t = time.time()
r = 0
for i in xrange(test_len):
	r = r+1
print 'globals : ', time.time() - t

# test locals
def test():
	r = 0
	for i in xrange(test_len):
		r = r+1

t = time.time()
test()
print 'locals : ', time.time() - t

# test psyco
psyco.full()
t = time.time()
test()
print 'psyco : ', time.time() - t

	And here are the timings :

globals :  0.571024894714
locals :  0.261034011841
psyco :  0.00352907180786

	As you can see locals are a lot faster than globals... and yes, the psyco  
figure is real, but this really is an extreme case, using only integers.  
Usually Psyco accelerates between nothing and 2-3x

	***************************************
	* About <:val:> tag
	In the generated sources, I see :

__d.CURRENT_TAG = "<:val '`title`':>"
__d.CURRENT_LINENO = '/webadmin/comps/products_list.comp:21'
__t.val = title
if __t.val is None:
     __t.val = ""
else:
     __t.val = str(__t.val)
__h.OUTPUT.write(__t.val)
del __t.val

	***************************************
	Comments :
	- I think it would be more appropriate to use a function for the  
following code :

	__t.val = title
	if __t.val is None:
	    __t.val = ""
	else:
	    __t.val = str(__t.val)
	__h.OUTPUT.write(__t.val)
	del __t.val

	Even if inlining looks faster, I guess it's much slower here, due to  
unoptimized globals, temp variable creation, and del. There is probably a  
reason you did it that way, though. It could also be a method in the  
OUTPUT object.

	And generally, I think it would be a good idea to use functions more  
often in the compiled templates (for argument extraction, too). This would  
make the code smaller (faster to compile, to load, takes less memory,  
better locality of reference in cache, etc.)

	You could also save a few lookups by putting __h.OUTPUT.write in a  
variable.

	***************************************
	* About debug info and generated sources size
	In the generated sources, I see :

__d.CURRENT_TAG = '<:val "`(\'Non\',  
\'Oui\')[prod.products_ready_to_ship]`":>'
__d.CURRENT_LINENO = '/webadmin/comps/products_list.comp:136'

	This is nice for debugging, however it causes code bloat.
	Same thing for including the sources in the compiled files.
	I think it would be better to create a file with only the compiled python  
bytecode (this is the file which is loaded all the time by SkunkWeb), and  
another file with the source and tag reference.

	Then, the compiled template would only contain lines like :
__d.CURRENT_POSITION  = (1, 10, 20)
	the tuple being : file id, tag id, line id (or something like that).
	One tuple = one assignment (instead of two)

	The tag, file, etc. would be retrieved from these ID's when an error  
occurs.

  	***************************************
	* Other notes :
	In the generated sources, I see :
         __d.CURRENT_TAG = "<:for '`prod.images`' 'image':>"
         __t.temp5 = prod.images
         if __t.temp5:
             for image in __t.temp5:

	You could use instead :
	for image in (prod.images or []):

	That's all I can think about right now. I hope it helps !

	Thanks a lot !



-------------------------------------------------------
This SF.Net email sponsored by Black Hat Briefings & Training.
Attend Black Hat Briefings & Training, Las Vegas July 24-29 - 
digital self defense, top technical experts, no vendor pitches, 
unmatched networking opportunities. Visit www.blackhat.com
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.