473,405 Members | 2,261 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

if not DEBUG: log = null_log


Hi,

I'm after a no-op command, so that i can redirect
logging commands in performance critical code.

Something like this:

def log(*args): print args
def null_log(*args): pass
if not DEBUG: log = null_log

is unacceptable because of the overhead of calling
functions in python.

log ("about to slip into python feature request mode.")

Maybe this is what the PEP 336 guy was thinking of (Make None Callable).
Obviously we don't want None to be callable, but
what about a "Null" [1] that's callable, with any args ?

But I guess what I am really asking for is something on the bytecode
level that tells the VM to "do nothing".

Here's an idea: make "pass" into an expression (a value) that is callable,
with any args, and returns None.

log ("finished with python feature request mode.")

I recently discovered "pyc" [2], but i don't quite see how i can
use it while maintaining python source compatability.

bye!

Simon.

[1]: http://occs.cs.oberlin.edu/~jwalker/nullObjPattern/
[2]: http://students.ceid.upatras.gr/~sxanth/pyc/

--
Simon Burton, B.Sc.
Licensed PO Box 8066
ANU Canberra 2601
Australia
Ph. 61 02 6249 6940
http://arrowtheory.com
Jul 21 '05 #1
3 1451
On Wed, 13 Jul 2005 11:00:14 +1000, Simon Burton wrote:
Hi,

I'm after a no-op command, so that i can redirect
logging commands in performance critical code.

Something like this:

def log(*args): print args
def null_log(*args): pass
if not DEBUG: log = null_log

is unacceptable because of the overhead of calling
functions in python.
Excuse my skepticism, but I'd like to see the profiling that you did that
shows this is a problem. Everybody thinks their code is performance
critical, even when it isn't.

So, let's do a test. First, I set up a fake object that requires lots of
name look-ups:
class Placeholder: .... pass
.... obj = Placeholder()
obj.method = Placeholder()
obj.method.attribute = Placeholder()
obj.method.attribute.record = None
Now I run a test to time those name lookups:
def test_func_overhead(n): .... loop = range(n)
.... t = time.time()
.... for i in loop:
.... f = obj.method.attribute.record
.... t = time.time() - t
.... return t
.... test_func_overhead(100000) 0.10761499404907227 test_func_overhead(100000) 0.13230800628662109 test_func_overhead(100000) 0.11942911148071289

Now set up a test bypassing the name lookups:
def test_func_no_overhead(n): .... loop = range(n)
.... y = obj.method.attribute.record
.... t = time.time()
.... for i in loop:
.... f = y
.... t = time.time() - t
.... return t
.... test_func_no_overhead(100000) 0.052425861358642578 test_func_no_overhead(100000) 0.042248010635375977 test_func_no_overhead(100000) 0.055256843566894531

So four global lookups performed 100,000 times takes 0.1 second, while a
single local lookup performed 100,000 times takes 0.05 second. Not a big
difference. Extrapolating from four lookups down to one would suggest
that global lookups are faster than local, which can't be right.

Redoing test_func_overhead to only make one lookup (change the
reference to obj.method.attribute.record to just obj) gives very
surprising results:
test_func_overhead2(100000) 0.041122913360595703 test_func_overhead2(100000) 0.037561893463134766 test_func_overhead2(100000) 0.020340204238891602

According to my testing, looking up a global variable is *faster* than
looking up a local. Hmmmm. Caching effects perhaps?

Try the local version again:
test_func_no_overhead(100000) 0.025532007217407227 test_func_no_overhead(100000) 0.016258001327514648 test_func_no_overhead(100000)

0.016184806823730469

Ah, that's better! At least now the local lookup is slightly faster
than the global. But also widely different from the first run. Function
lookup is so fast to start with, and affected by so many external factors,
that the cost-benefit equation of trying to optimize it is not very good.
There almost certainly will be more useful things for you to spend your
time on.

More comments below:-
log ("about to slip into python feature request mode.")

Maybe this is what the PEP 336 guy was thinking of (Make None Callable).
Obviously we don't want None to be callable, but
what about a "Null" [1] that's callable, with any args ?

But I guess what I am really asking for is something on the bytecode
level that tells the VM to "do nothing".

Here's an idea: make "pass" into an expression (a value) that is callable,
with any args, and returns None.

log ("finished with python feature request mode.")
And how do you use this without the overhead of function calls?

Do you sprinkle your code with:

if DEBUG:
log("spam")
else:
pass("spam")

?

Why not just do this?

if DEBUG: log("spam")

Which is much simpler. Or even simpler still, put the "if DEBUG" test
inside log, since the extra time taken in calling the function is probably
lost in the noise of the rest of your code.


Not related to the logging issue:
I recently discovered "pyc" [2], but i don't quite see how i can
use it while maintaining python source compatability. [snip] [2]: http://students.ceid.upatras.gr/~sxanth/pyc/


How fascinating. From the pyc page:

"In fact you can use pyc to re-compile your standard library and make it
about 100kB smaller."

Hmmm. Let's see now, Python 2.3.3 on Fedora Core 2:

$ du -hs /usr/lib/python2.3/
88M /usr/lib/python2.3/

Oh joy! So by using pyc, I can save 0.11% of the Python library storage
requirements!

For all I know, pyc is a very useful package, and kudos to the author for
taking the time and effort to develop it. But if this space saving is
"one good reason to use pyc" according to the author, I'm not impressed.
--
Steven.

Jul 21 '05 #2
On Wed, 13 Jul 2005 11:00:14 +1000, Simon Burton <si***@arrowtheory.com> wrote:

Hi,

I'm after a no-op command, so that i can redirect
logging commands in performance critical code.

Something like this:

def log(*args): print args
def null_log(*args): pass
if not DEBUG: log = null_log

is unacceptable because of the overhead of calling
functions in python.

I think you could make the existence of log calls dependent on
whether you compile with an optimize flag by abusing
an assert statement, e.g.,

assert log(some, args) or True

would always make the call in debug mode, but would never raise the exception
because of the "or True", even if log return None. If you compile with optimization,
the entire assert statement disappears from the byte code, UIAM.

if you use

if __debug__: log(some, args)

I think[1] you still the the if-test code, though that is pretty quick
compared to a function call, so maybe you don't have to worry about it,
unless it is in a super-hot loop.

[1] I thought is saw somewhere that
if __debug__: suite
might be completely optimized away like assert, but I couldn't locate it off hand.
It would seem pretty safe and useful though.

Regards,
Bengt Richter
Jul 21 '05 #3
Bengt Richter wrote:
On Wed, 13 Jul 2005 11:00:14 +1000, Simon Burton <si***@arrowtheory.com> wrote:

Hi,

I'm after a no-op command, so that i can redirect
logging commands in performance critical code.

Something like this:

def log(*args): print args
def null_log(*args): pass
if not DEBUG: log = null_log

is unacceptable because of the overhead of calling
functions in python.


I think you could make the existence of log calls dependent on
whether you compile with an optimize flag by abusing
an assert statement, e.g.,

assert log(some, args) or True


This is a session with the -O flag, so asserts disapear:
from time import time

def count(N=10000000): .... for i in xrange(N): i=0
....
t=time(); count(); print time()-t
0.821492910385
def count_call(N=10000000): .... for i in xrange(N): foo()
.... t=time(); count_call(); print time()-t 3.50276303291
def log(): print "log" ....
def count_assert(N=10000000): .... for i in xrange(N): assert log()
....
t=time(); count_assert(); time()-t

0.61060500144958496

Woohoo!!
Simon.
Jul 21 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Davy | last post by:
Hi all, I use VC and gcc/gdb to compile and debug C/C++ files. But I found some of the debug version of the compiled files are too large to be run in a small RAM. Can I compile C/C++ Debug...
4
by: emma middlebrook | last post by:
I have a question regarding asserting ... here's some code: string GetAssertMessage() { ... prepare a message string and return it... } void SomeMethod() { ...
7
by: Srinivasa Rao | last post by:
I have read in one article that when we compile the application in release mode, all the debug classes and properties will be automatically removed from the code. I tried to implement this thing by...
9
by: dee | last post by:
Hi I'm about to upload my site and I have switched to release version. Is that enough or do I still need to disable <compilation defaultLanguage="vb" debug="true" /> the debug="true" in the .pdb...
6
by: swartzbill2000 | last post by:
Hello, I have a VB 2005 Express project with a TraceListener-derived class to route Debug.Print output to a log file. It works fine for Debug builds. What is the correct combination of changes to...
6
by: pauldepstein | last post by:
To help me debug, I am writing a lot of information into a stream which I call debug. However, because of the large amount of time taken to print this information, I only want this printed while...
6
by: Andrew Rowley | last post by:
I am having trouble getting debug and release builds to work properly with project references using C++ .NET and Visual Studio 2003. I created a test solution, with a basic Windows form C++...
0
by: BA | last post by:
I posted on this once before and could not get a solution, I am hoping someone can help. I have a very strange code debug behavior that I cannot make heads or tails of: I have c# code being...
3
by: rorni | last post by:
Hi, I'm porting code from Windows to HP-UX 11, compiling with g++. I'm getting a compilation error on the system's debug.h include file, which is included very indirectly through a series of...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.