Can you make this faster?

alejandro david weil aweil at mail.ru
Sun Jun 27 17:34:50 EDT 2004


On Sun June 27 2004 15:22, Kamilche wrote:
> I have a routine that I really need, but it slows down processing
> significantly. Can you spot any ineffeciencies in the code?
>
> This code makes a critical function of mine run about 7x slower than
> using a prebuilt format string. For maximum flexibility, it would be
> best to calculate the format string using this method, so I'd dearly
> love to keep it.
>
> def fmtstring(args):
>     delim = '\0'
>     fmt = []
>     fmt.append('<')
>     for arg in args:
>         t = type(arg)
>         if t == types.StringType:
>             l = len(arg)
>             fmt.append(str(l) + 's')
>         elif t == types.IntType:
>             fmt.append('i')
>         elif t == types.LongType:
>             fmt.append('q')
>         elif t == types.BooleanType:
>             fmt.append('c')
>         elif t == types.FloatType:
>             fmt.append('d')
>         else:
>             raise Exception("Can't pack argument of type %s!" % t)
>     s = ''.join(fmt)
>     s = s + '\0'
>     return s

I've tried this:
import types

def fmtstring(args):
	delim = '\0'
	fmt = []
	fmt.append('<')
	for arg in args:
		t = type(arg)
		if t == types.StringType:
			l = len(arg)
			fmt.append(str(l) + 's')
		elif t == types.IntType:
			fmt.append('i')
		elif t == types.LongType:
			fmt.append('q')
		elif t == types.BooleanType:
			fmt.append('c')
		elif t == types.FloatType:
			fmt.append('d')
		else:
			raise Exception("Can't pack argument of type %s!" % t)
	s = ''.join(fmt)
	s = s + '\0'
	return s

typedic = {
	types.StringType : 's',
	types.IntType: 'i',
	types.LongType: 'q',
	types.BooleanType: 'c',
	types.FloatType:'d'}

def myfmtstring(args):
	global typedic
	f2 = '<'
	t = None
	for arg in args:
		t = type(arg)
		if t == types.StringType:
			f2 += str(len(arg))
		try:
			f2 += typedic[t]	
		except: #check the exception here!
			raise Exception("Can't pack argument of type %s!" % t)
	return f2+'\0' 

if __name__=='__main__':
	import unittest
	TIMES = 10000

	class TestFmtFuncBase(unittest.TestCase):
		def setUp(self):
			self.what = ['hola','que','tal',324,454,False]

		def runFuncOnce(self):
			#shouldnt be here!
			assert(False)

		def runFuncTimes(self, times=TIMES):
			for i in xrange(times):
				self.runFuncOnce()


	class TestFunction1(TestFmtFuncBase):
		def runFuncOnce(self):
			return fmtstring(self.what)
		def testSpeed(self):
			"""Run function a lot of times to check its time"""
			self.runFuncTimes()
		def testValue(self):
			"""Check return value"""
			print self.runFuncOnce()

	class TestFunction2(TestFmtFuncBase):
		def runFuncOnce(self):
			return myfmtstring(self.what)
		def testSpeed(self):
			"""Run function a lot of times to check its time"""
			self.runFuncTimes()
		def testValue(self):
			"""Check return value"""
			print self.runFuncOnce()

	
	suiteOriginal = unittest.TestSuite()
	suiteOriginal.addTest(unittest.makeSuite(TestFunction1))
	suiteNew = unittest.TestSuite()
	suiteNew.addTest(unittest.makeSuite(TestFunction2))

	unittest.TextTestRunner(verbosity=2).run(suiteOriginal)
	unittest.TextTestRunner(verbosity=2).run(suiteNew)

And seems to be not faster:

----------------------------------------------------------------------
Run function a lot of times to check its time ... ok
Check return value ... <4s3s3siic
ok

----------------------------------------------------------------------
Ran 2 tests in 0.477s

OK
Run function a lot of times to check its time ... ok
Check return value ... <4s3s3siic
ok

----------------------------------------------------------------------
Ran 2 tests in 0.396s

OK


But, anyway, the problem seems to be the:
	f2 += str(len(arg))
line.

If you take it off, you'll see that time reduces to half!
Why? How to fix?
Don't know! :-(

Sorry,
dave
-- 
+ There is no dark side of the moon really. Matter of fact it's all dark.





More information about the Python-list mailing list