472,374 Members | 1,446 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

Defaultdict and speed

This post sums some things I have written in another Python newsgroup.
More than 40% of the times I use defaultdict like this, to count
things:
>>from collections import defaultdict as DD
s = "abracadabra"
d = DD(int)
for c in s: d[c] += 1
....
>>d
defaultdict(<type 'int'>, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})

But I have seen that if keys are quite sparse, and int() becomes called
too much often, then code like this is faster:
>>d = {}
for c in s:
.... if c in d: d[c] += 1
.... else: d[c] = 1
....
>>d
{'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1}

So to improve the speed for such special but common situation, the
defaultdict can manage the case with default_factory=int in a different
and faster way.

Bye,
bearophile

Nov 3 '06 #1
3 4050
be************@lycos.com wrote:
This post sums some things I have written in another Python newsgroup.
More than 40% of the times I use defaultdict like this, to count
things:
>from collections import defaultdict as DD
s = "abracadabra"
d = DD(int)
for c in s: d[c] += 1
...
>d
defaultdict(<type 'int'>, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})

But I have seen that if keys are quite sparse, and int() becomes called
too much often, then code like this is faster:
>d = {}
for c in s:
... if c in d: d[c] += 1
... else: d[c] = 1
...
>d
{'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1}

So to improve the speed for such special but common situation, the
defaultdict can manage the case with default_factory=int in a different
and faster way.
Benchmarks? I doubt it is worth complicating defaultdict's code (and
slowing down other uses of the class) for this improvement...
especially when the faster alternative is so easy to code. If that
performance difference matters, you would likely find more fruitful
gains in coding it in c, using PyDict_SET.

-Mike

Nov 4 '06 #2
Klaas wrote:
Benchmarks?
There is one (fixed in a succesive post) in the original thread I was
referring to:
http://groups.google.com/group/it.co...f60c644969f9b/
If you want I can give more of them (and a bit less silly, with strings
too, etc).

def ddict(n):
t = clock()
d = defaultdict(int)
for i in xrange(n):
d[i] += 1
print round(clock()-t, 2)

def ndict(n):
t = clock()
d = {}
for i in xrange(n):
if i in d:
d[i] += 1
else:
d[i] = 1
print round(clock()-t, 2)

ddict(300000)
ndict(300000)

(and slowing down other uses of the class)
All it has to do is to cheek if the default_factory is an int, it's
just an "if" done only once, so I don't think it slows down the other
cases significantly.

especially when the faster alternative is so easy to code.
The faster alternative is easy to create, but the best faster
alternative can't be coded, because if you code it in Python you need
two hash accesses, while the defaultdict can require only one of them:

if n in d:
d[n] += 1
else:
d[n] = 1

>If that performance difference matters,
With Python it's usually difficult to tell if some performance
difference matters. Probably in some programs it may matter, but in
most other programs it doesn't matter. This is probably true for all
the performance tweaks I may invent in the future too.

you would likely find more fruitful
gains in coding it in c, using PyDict_SET
I've just started creating a C lib for related purposes, I'd like to
show it to you all on c.l.p, but first I have to find a place to put it
on :-) (It's not easy to find a suitable place, it's a python + c +
pyd, and it's mostly an exercise).

Bye,
bearophile

Nov 4 '06 #3
be************@lycos.com wrote:
Klaas wrote:
Benchmarks?

There is one (fixed in a succesive post) in the original thread I was
referring to:
http://groups.google.com/group/it.co...f60c644969f9b/
If you want I can give more of them (and a bit less silly, with strings
too, etc).
<>

Sorry, I didn't see any numbers. I ran it myself and found the
defaultdict version to be approximately twice as slow. This, as you
suggest, is the worst case, as you are using integers as hash keys
(essentially no hashing cost) and are accessing each key exactly once.
>
(and slowing down other uses of the class)

All it has to do is to cheek if the default_factory is an int, it's
just an "if" done only once, so I don't think it slows down the other
cases significantly.
Once it makes that check, surely it must check a flag or some such
every time it is about to invoke the key constructor function?
especially when the faster alternative is so easy to code.

The faster alternative is easy to create, but the best faster
alternative can't be coded, because if you code it in Python you need
two hash accesses, while the defaultdict can require only one of them:

if n in d:
d[n] += 1
else:
d[n] = 1
How do you think that defaultdict is implemented? It must perform the
dictionary access to determine that the value is missing. It must then
go through the method dispatch machinery to look for the __missing__
method, and execute it. If you _really_ want to make this fast, you
should write a custom distionary subclass which accepts an object (not
function) as default value, and assigns it directly.
If that performance difference matters,

With Python it's usually difficult to tell if some performance
difference matters. Probably in some programs it may matter, but in
most other programs it doesn't matter. This is probably true for all
the performance tweaks I may invent in the future too.
In general, I agree, but in this case it is quite clear. The only
possible speed up is for defaultdict(int). The re-write using regular
dicts is trivial, hence, for given piece of code is it quite clear
whether the performance gain is important. This is not an
interpreter-wide change, after all.

Consider also that the performance gains would be relatively
unsubstantial when more complicated keys and a more realistic data
distribution is used. Consider further that the __missing__ machinery
would still be called. Would the resulting construct be faster than
the use of a vanilla dict? I doubt it.

But you can prove me wrong by implementing it and benchmarking it.
you would likely find more fruitful
gains in coding it in c, using PyDict_SET

I've just started creating a C lib for related purposes, I'd like to
show it to you all on c.l.p, but first I have to find a place to put it
on :-) (It's not easy to find a suitable place, it's a python + c +
pyd, and it's mostly an exercise).
Would suggesting a webpage be too trite?

-Mike

Nov 5 '06 #4

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

Similar topics

13
by: Yang Li Ke | last post by:
Hi guys, Is it possible to know the internet speed of the visitors with php? Thanx -- Yang
34
by: Jacek Generowicz | last post by:
I have a program in which I make very good use of a memoizer: def memoize(callable): cache = {} def proxy(*args): try: return cache except KeyError: return cache.setdefault(args,...
0
by: Steven Bethard | last post by:
Steven Bethard wrote: > Agreed. I really hope that Python 3.0 applies Raymond Hettinger's > suggestion "Improved default value logic for Dictionaries" from > ...
3
by: Raymond Hettinger | last post by:
FWIW, here are three ways of writing constant functions for collections.defaultdict(): d = defaultdict(int) # slowest way; works only for zero d = defaultdict(lambda: 0) # faster way;...
2
by: tutufan | last post by:
It seems like x = defaultdict(defaultdict(list)) should do the obvious, but it doesn't. This seems to work y = defaultdict(lambda: defaultdict(list)) though is a bit uglier.
2
by: metaperl.com | last post by:
I'm reading http://norvig.com/spell-correct.html and do not understand the expression listed in the subject which is part of this function: def train(features): model =...
3
by: fizilla | last post by:
Hello all! I have the following weird problem and since I am new to Python I somehow cannot figure out an elegant solution. The problem reduces to the following question: How to pickle a...
7
by: Matthew Wilson | last post by:
I used defaultdict.fromkeys to make a new defaultdict instance, but I was surprised by behavior: defaultdict(None, {'y': <type 'list'>, 'x': <type 'list'>}) <type 'list'> ...
4
by: nestle | last post by:
I have DSL with a download speed of 32MB/s and an upload speed of 8MB/s(according to my ISP), and I am using a router. My upload speed is always between 8MB/s and 9MB/s(which is above the max upload...
0
by: Naresh1 | last post by:
What is WebLogic Admin Training? WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge required to effectively administer and manage Oracle...
0
hi
by: WisdomUfot | last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific technical details, Gmail likely implements measures...
0
Oralloy
by: Oralloy | last post by:
Hello Folks, I am trying to hook up a CPU which I designed using SystemC to I/O pins on an FPGA. My problem (spelled failure) is with the synthesis of my design into a bitstream, not the C++...
0
BLUEPANDA
by: BLUEPANDA | last post by:
At BluePanda Dev, we're passionate about building high-quality software and sharing our knowledge with the community. That's why we've created a SaaS starter kit that's not only easy to use but also...
0
by: Rahul1995seven | last post by:
Introduction: In the realm of programming languages, Python has emerged as a powerhouse. With its simplicity, versatility, and robustness, Python has gained popularity among beginners and experts...
2
by: Ricardo de Mila | last post by:
Dear people, good afternoon... I have a form in msAccess with lots of controls and a specific routine must be triggered if the mouse_down event happens in any control. Than I need to discover what...
1
by: Johno34 | last post by:
I have this click event on my form. It speaks to a Datasheet Subform Private Sub Command260_Click() Dim r As DAO.Recordset Set r = Form_frmABCD.Form.RecordsetClone r.MoveFirst Do If...
1
by: ezappsrUS | last post by:
Hi, I wonder if someone knows where I am going wrong below. I have a continuous form and two labels where only one would be visible depending on the checkbox being checked or not. Below is the...
0
DizelArs
by: DizelArs | last post by:
Hi all) Faced with a problem, element.click() event doesn't work in Safari browser. Tried various tricks like emulating touch event through a function: let clickEvent = new Event('click', {...

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.