An awesome presentation by Robert Brewer from PyCon 2010. Make sure you watch at a comfortable time.
It’s good to see CherryPy project is pretty much alive. It’s a web server and a web framework and more. Check it out if you haven’t!
An awesome presentation by Robert Brewer from PyCon 2010. Make sure you watch at a comfortable time.
It’s good to see CherryPy project is pretty much alive. It’s a web server and a web framework and more. Check it out if you haven’t!
I wrote “signals provide a great way to propagate the events generated from your app” earlier. I think reusable apps should avoid hardcoding any kind of event handling and send signals instead. App consumers might prefer an email over an on-screen notification. They may even choose to ignore the event silently. A reusable app should give this choice to the consumer.
Taking advantage of signals doesn’t necessarily mean providing no sane defaults. You can send signals and provide default event handling. Here is a couple of ideas how this can be done:
INSTALLED_APPS.I personally prefer the second approach since it’s simpler and more explicit. I’m sure there are other ways to implement default handlers for signals.
Don’t forget to assign a unique dispatch_uid for each connect() call. Otherwise your handler can get connected twice. I would also suggest you to use both module path and your handler function’s name in your dispatch_uid:
"%s.%s" % (os.path.splitext(__file__)[0].replace(os.sep, '.')[1:],
handler_name)
Now I should take my own advice and replace hardcoded User.message_set.create()s with signals in django-simple-friends.
Recently I have done some optimizations to make telvee a little faster using django_compressor and making sprites for background images. Good news is substantial changes to development environment and the design wasn’t required. I’ll get into details below. But first I’d like to write about the theory a little bit.
I follow (and read with great interest) Steve Souders’s blog High Performance Web Sites. I must admit I was sceptical about it at first; spriting images, individual different loading behaviours of browsers… I thought they were premature optimizations. But I realized I was wrong as I continued to read. Steve Souders is an expert on high performance web sites and what he preaches are realistic techniques, backed by test results most of the time. If you are not following, I suggest you add it to your RSS reader.
We can explore the techniques in two main categories:
data: URI’s. Extra HTTP requests for those resources can be avoided this way.You might think it’s fine to perform all these optimizations, but what happens when I want to make some changes to my combined, minified JavaScript file? Instead of applying these techniques blindly, it’s best to follow a sensible plan for implementing these optimizations:
I didn’t think about performance at all when I started developing telvee. Too many CSS files and too many images were being loaded. Here is what it looked like before optimizations:
| # of requests | load (KB) | |
|---|---|---|
| Homepage | 25 | ~85 |
| Cup Detail | 48 | ~80 |
Then I have installed and configured django_compressor. I used YUI Compressor for both JavaScript and CSS. I have created sprites and modified CSS files manually1. Then I deployed these changes and measured again:
| # of requests | load (KB) | |
|---|---|---|
| Homepage | 12 | ~70 (~160) |
| Cup Detail | 14 | ~64 |
In the load column of Homepage, the number in parens is the actual load. But the design of homepage is changed with this upgrade and a new 90 KB image is being loaded now. So I have accepted 70 KB in my calculations. The result of optimizations are as follows:
| # of requests | load (KB) | |
|---|---|---|
| Homepage | 52% | 17% |
| Cup Detail | 70% | 19% |
Django_compressor, developed by Christian Metts, helps you to apply optmizations I have mentioned above easily to your Django projects. You can see my fork here where I have merged some other branches and added a little bit of code myself.
Using compressor.filters.datauri.CssDataUriFilter in data-uri branch of this repository, you can embed linked files within your CSS files. It will only embed files less than or equal to 1024 Bytes (1 KB) by default. You can change this limit by setting COMPRESS_DATA_URI_MIN_SIZE in your settings.py.
There are a couple of things to pay attention when you convert your references to data: URIs. Firstly file contents are base64 encoded which means approximately one third increase in size. It’s up to you to balance between increased bandwidth and reduced request counts2. Another thing to watch for is multiple references to the same file will end up embedding the same data many times. The solution to this problem is to reduce all references to one3 but this might break your CSS arrangement strategy.
Please test django_compressor’s data: URI support and tell me what you think. If you haven’t applied optimizations I mentioned above, you should. Thanks to django_compressor they are quite easy to implement on Django projects.
1: I would like to add automatic sprite building/linking support to django_compressor sometime.
2: With Today’s modern connections 1~2 KB increase is a good price for 1 less HTTP request..
3: http://meiert.com/en/blog/20090401/why-css-needs-no-variables/
I have wealthy friends, I have friends who are doing worse than me. Most of my friends are university graduates, some of them barely finished primary school. I don’t pay too much attention of their attractiveness but some of them ought to be more beautiful than others. Some of my friends speak with a clear, good accent while others have strong eastern accents. You might find the way they speak funny. But I don’t. I make friends with people who are streetwise and resourceful. You might call some other friends of mine “mother’s darling”. Of all these things I have mentioned above; none of them factor in how close a friend is to me. I wouldn’t go so far as to say I don’t care. But they are definitely not determining factors for my friendships. I don’t discriminate people based on their social status, education, appearance, etc.
My relationship doesn’t go very far with somebody who is not a man of his word. My close friends are punctual, reliable and they keep their promises. I don’t hang out with snobs, envious, scornful people. But the most important qualities I look for in a friend is being cultivated and refined and open minded. I am attracted to people who has a spark in their eyes. You know, the opposite of being a zombie. I make very strong distinctions on these matters. Everybody wants to have nice friends. I’m a nazi about it. I’d rather not waste any time on shallow people and their silly affairs.
We live in a society where any and all kinds of discrimination is frowned upon. I call this “but he is a good guy” disorder. That but clearly indicates there is something not good about that guy, he is not all-good. Scrape any negative attribute off of people. Are we all equally honest? Are we all self-sacrificing and understanding? And then that guy is actually a very nice person. Very nice my ass.
Discrimination based on gender or color or whatever superficial feature is bad. Even kindergarden children know that. Not discriminating at all is idiotic at best and bad for the society at worst. You have to make a choice between people, you can’t be intimate with everybody. You better not base your choice on stupid criteria like coolness or popularity or, god forbid, assertiveness. This is the exact same mistake we make choosing our rulers… ehm, I mean political representatives.
This is not just about human beings. We need to pick out the good from bad when we are making spending decisions. I have seen Food, Inc. recently and it talks about this (near the end). Corporations hide behind many layers of obscurity and we don’t easily see how they are doing their business. To compound that we, as individuals, think ourselves as too small to matter against big companies. But the truth is the only thing we can do happens to be a very powerful way to send them a message. If a company is evil, don’t buy its product. You can’t do much else anyway, but this one act should be enough.
So, make a choice. Or not. Choice is yours.