Good news everyone!
This blog post by Dan Crosta is interesting. It talks about how is possible to optimise Python code for operations that get called multiple times avoiding the usage of Object Orientation and using Closures instead.
While the “closures” gets the highlight, the main idea is a little more general. Avoid repeating code that is not necessary for the operation.
The difference between the first proposed code, in OOP way
class PageCategoryFilter(object): def __init__(self, config): self.mode = config["mode"] self.categories = config["categories"] def filter(self, bid_request): if self.mode == "whitelist": return bool( bid_request["categories"] & self.categories ) else: return bool( self.categories and not bid_request["categories"] & self.categories )
and the last one
def make_page_category_filter(config): categories = config["categories"] mode = config["mode"] def page_category_filter(bid_request): if mode == "whitelist": return bool(bid_request["categories"] & categories) else: return bool( categories and not bid_request["categories"] & categories ) return page_category_filter
The main differences are that both the config dictionary and the methods (which are also implemented as a dictionary) are not accessed. We create a direct reference to the value (categories and mode) instead of making the Python interpreter search on the self methods over and over.
This generates a significant increase in performance, as described on the post (around 20%).
But why stop there? There is another clear win in terms of access, assuming that the filter doesn’t change. This is the “mode”, which we are comparing for whitelist of blacklist on each iteration. We can create a different closure depending on the mode value.
def make_page_category_filter2(config): categories = config["categories"] if config['mode'] == "whitelist": def whitelist_filter(bid_request): return bool(bid_request["categories"] & categories) return whitelist_filter else: def blacklist_filter(bid_request): return bool( categories and not bid_request["categories"] & categories ) return blacklist_filter
There are another couple of details. The first one is to transform the config categories into a frozenset. Assuming that the config doesn’t change, a frozenset is more efficient than a regular mutable set. This is insinuated in the post, but maybe didn’t get the final review (or to simplify it).
Also, we are calculating the intersection of a set (operand &) to then reduce it to a bool. There is currently a set operation that gets the result without calculating the whole intersection (isdisjoint).
The same basic principle applies to calculate the bool category for the black filter. We can calculate it only once, as it’s there to short-circuit the result in case of an empty config category.
def make_page_category_filter2(config): categories = frozenset(config["categories"]) bool_cat = bool(categories) if config['mode'] == "whitelist": def whitelist_filter(bid_request): return not categories.isdisjoint(bid_request["categories"]) return whitelist_filter else: def blacklist_filter(bid_request): return (bool_cat and categories.isdisjoint(bid_request["categories"])) return blacklist_filter
Even if all of this enters the definition of micro-optimisations (which should be used with care, and only after a hot spot has been found), it actually makes a significant difference, reducing the time around 35% from the closure implementation and ~50% from the initial reference implementation.
All these elements are totally applicable to the OOP implementation, by the way. Python is quite flexible about assigning methods. No closures!
class PageCategoryFilter2(object): ''' Keep the interface of the object ''' def __init__(self, config): self.mode = config["mode"] self.categories = frozenset(config["categories"]) self.bool_cat = bool(self.categories) if self.mode == "whitelist": self.filter = self.filter_whitelist else: self.filter = self.filter_blacklist def filter_whitelist(self, bid_request): return not bid_request["categories"].isdisjoint(self.categories) def filter_blacklist(self, bid_request): return (self.bool_cat and bid_request["categories"].isdisjoint(self.categories))
Here is the updated code, adding this implementations to the test.
The results in my desktop (2011 iMac 2.7GHz i5) are
total time (sec) time per iteration class 9.59787607193 6.39858404795e-07 func 8.38110518456 5.58740345637e-07 closure 7.96493911743 5.30995941162e-07 class2 6.00997519493 4.00665012995e-07 closur2 5.09431600571 3.39621067047e-07
The new class performs better than the initial closure! The optimised closure is anyway trumping, saving a big chunk compared with the slower implementation. The PyPy results are all very close, and it speeds up 10x the code, which is an amazing feat.
Of course, a word of caution. The configuration is assumed to not change for a filter, which I think is reasonable.
Today John Siracusa announced that he won’t be making more OS X reviews.
Typically journalists or reviewers don’t announce that they stop doing something. They just stop doing it, and maybe explain it after someone asks them.
But John’s reviews were something truly special, and a lot of people on the tech world has lamented the announcement.
I think that the Mac community has always been quite vibrant and passionate, allowing detailed discussion. Crossing the line of obsession sometimes. In other tech worlds, the discussion is more cold and rational, even aseptic. Apple discussion has always been more emotional and sort of aiming for greatness. Years ago the distinction was quite pronounced, when Apple had a small and passionate group of followers.
Tech reviews tend to be on two extremes. Either too much spec and features enumeration, making them arid and boring. Or too much focused in fitting a narrative, talking about whether something is the best or the worst ever.
But these OS X reviews are the perfect combination of both aspects, and they remain the gold standard of tech literature.
John’s reviews are extremely detailed, even to the level of obsession, but yet they are easy to read and understand.
They present a clear exposure of new features. But add historical context of decisions, compromises and forecasting areas of improvement.
Siracusa has strong opinions in quite a few areas, but he’s exposing all the facts, and explaining his biases.
I can’t stress how difficult is keep you hooked and eager to read another 8,000 words, when you’re talking in length about filesystems, pixel alignment, background process handling or Finder performance.
I haven’t found anything that can be on par, though there are great writers writing about technology these days. I can read better reviews now than 5 or 10 years ago.
While I understand his reasons for stopping, and think we have been lucky to have them around for so long, I can’t help but feel a little sad.
I’ll keep following him in his blog, twitter, and of course on his weekly podcast, as well as collaborations. At least, John Siracusa keeps a healthy production that we can consume. I’m sure we’ll keep reading and listening great stuff.
The importance of Spock as an icon of the XX century cannot be overstated.
Let me go back for a second. When I was a child in Spain, access to Star Trek was pretty limited. There were no reruns of the original series. I think it only was emitted during the 70s in Black and White. The Next Generation was broadcasted with a four or five year delay. And it stopped for several years just at the end of the third season. It took me years to know what happened with Picard and Locutus! Also, the movies were not big hits.
But everyone knew who Spock was. A lot of people told my uncle he looked like “Dr” Spock. He beared a clear resemblance with Leonard Nimoy when he was young.
In a lot of ways I’ve always consider Star Trek my “prime geeky love“. That iconic status and mystery, made me search for it. After having access to Internet, I devour everything about it. It was “my thing“, more than other stuff I love, because it was less known among my circles. I bought the whole DS9 series in VHS from UK, over the course of several years. I say that I learned spoken English through Star Trek. And written English through RPG manuals.
Spock is the most genuine example of “cool scientist“, in opposition from the “mad scientist” trope . Probably the first example. And was the one getting the spotlight in the series. He was the character to follow.
He is iconic to a level that only competes with a bunch of icons. I’ve seen him in posters of parties or t-shirts in big stores. He’s know by people that don’t even know what Star Trek is.
And none of this should been possible without the extraordinary performance by Leonard Nimoy. It is clear that he contributed heavily to a lot of things that define Spock. From the Vulcan Nerve Pinch to the Vulcan salute. But his biggest legacy is the fact that his performance is replicated constantly. Every single Vulcan in Star Trek is impersonating Leonard Nimoy playing Spock. In tons of other media we have similar interpretations of “emotionless aliens/outsiders“. He created an archetype, which is a huge achievement. That is also a heavy burden, and Leonard Nimoy seemed only to embrace it after years of struggle.
There is also an overlooked idea in Vulcan philosophy that has always been appealing to me. IDIC. Infinite Diversity in Infinite Combinations. It resonates in me in a lot of diff
erent levels. On the personal level, on how important is to embrace the diversity that us humans are capable of produce.
And to the software creation, on how wonderful is the combination of different code, assembled to produce something magical together.
Leonard Nimoy will be greatly missed. Rest In Peace.
Life long and prosper.
More great reads!
Isn’t it quite absurd that we haven’t nail this yet?
We recently heard about all the great advances in terms of image quality, 4K, bending screens… Yet controlling a TV feels clunky and awkward.
Even worse, given the never ending increase in devices connected to the TV (DVDs, Blu Rays, AppleTVs, consoles…) the usage of different remote controls is painful, unless a Universal Remote is used. But even in that case, the process itself of selecting the activity is weird, for very common operations.
For example, if you want to play a movie on an AppleTV (or DVD player, or TiVO, etc), you may have to turn it on, then (using the remote), turn on the TV, select the input (which may involve cycle through a lot of unused inputs, like Composite), adjust the volume, and then get the AppleTV controller.
If at any point we need to adjust the volume, we’ll need to get again the TV remote.
All this is very weird and not the best user experience…
So, just for the sake of discussion, let’s say a couple of ideas for what I think could be a TV with a much better interface:
– Everything is a channel. Why HDMI is “an input” but TV channels are numbered? Allowing to select HDMI input as channel 3 allow easy access to it, and simplifies the interface.
If there is no input (e.g. the DVD is off), the channel will be skipped for channel surfing purposes, unless the user specifically request the channel number.
– A good remote. I don’t think that there’s any excuse for not being Universal and Programable Remote. The included TV Remote should aim to control more things than just the TV. It should have as few buttons as possible, more on that later. And, another important feature, it should be possible to make it beep if lost (e.g. clicking a button on the TV)
– Programmable channels. When a channel is on selected, all the settings (mainly image controls, but may also include a volume adjustment) will change accordingly. The remote will also know that the controls are now related to this channel. For example, if the DVD channel is selected, most of the keys are related to the DVD remote (except volume keys); if the AppleTV channel is selected, the keys refer to the AppleTV controls.
A list of channels (ideally showing their current input) that allows easy rearrangement and enabling disabling them will be great to navigate and give an overview.
– A companion app that allows to configure all the parameters easily on a PC or mobile app.
I understand that the complexities of the different devices in the living room is complex, and that there are problems that can be impossible to fix (for example, having an HDMI router may still present problems given that more than one “channel” will be coming from the same “input”)
But I find quite ridiculous that we are still dealing with such terrible interfaces in TVs these days…
Here we go again… This time I’m loosely grouping them, it has been a while and there are so many things!