This guy says just that. I don’t find his conclusions all that groundbreaking. But I really loved his focus on “It’s a record store”.
I’m pretty sure that’s not there is to it being a success. He, disguisedly, says that curating your content is fundamental. And he’ll charge you for that.
I have a bootcamp’ed Macbook Pro. As many people, I experienced some lagging sound and graphics from the computer, apparently at random. I googled it a bit, and found DPCs were the cause of it. And the cause DPCs were so slow were some drivers and KbdMgr.exe, a small app that listens to the hardware keys to raise brightness and stuff.
I updated the drivers, and the lag dropped a bit, but not that much. Then I turned to KbdMgr.exe. I read that a quick fix was to set the affinity to the second core and set it to minimum priority. And so I did, and it worked! However, It was just a pain in the butt to do that dance on each boot. I thought of doing some wrapper exe for KbdMgr.exe, but just the thought of downloading Visual Studio and all the SDKs gave me nauseas. And python popped into my mind.
After some 15 minutes of research, I found win32all. And from there, It was just remembering all of the win32 I had forgotten. I eventually churned out some code to scratch my itch.
import win32api
import win32com.client
import win32process
import win32con
import time
import sys, traceback
class ProcessSeekerThrottler(object):
def __init__(self):
self.coup_de_grace = self.throttle_and_set_affinity
self.backoff_interval = 1.0
def throttle_and_set_affinity(self,pid):
proc = win32api.OpenProcess(win32con.PROCESS_SET_INFORMATION, 0, pid)
win32process.SetProcessAffinityMask(proc,0x02)
win32process.SetPriorityClass(proc,win32process.IDLE_PRIORITY_CLASS)
win32api.CloseHandle(proc)
def pids_for(self,process_name):
self.WMI = win32com.client.GetObject('winmgmts:')
results = self.WMI.ExecQuery('select * from Win32_Process where Name="%s"'%(process_name,))
if len(results) < 1:
raise Exception("Not found: %s"%(process_name,))
else:
return [result.Properties_('ProcessId').Value for result in results]
def hunt_pid_for(self,process_name):
done = False
while not done:
try:
[self.coup_de_grace(pid) for pid in self.pids_for(process_name)]
print "Killed!"
done = True
except Exception as e:
print >> sys.stderr, "-"*60
traceback.print_exc(None,sys.stderr)
print >> sys.stderr, "Backing off."
time.sleep(self.backoff_interval)
if __name__ == '__main__':
try:
ProcessSeekerThrottler().hunt_pid_for("KbdMgr.exe")
except Exception as e:
traceback.print_exc(None,sys.stderr)
raw_input()
Pre scriptum: This was dangling in my drafts forever. I just decided to post it as it is.
In this post: Why I use Mercurial (sometimes abbreviated as hg) but not Git, and why I like it.
One day, some moons ago, I watched a presentation with Linus on Git, and how it would forever change our life. He explained why it’s a must-use on a very big distributed team or/and at a personal level. I mostly agreed. I still thought this was just a clever hack to solve merge conflits on svn and keep changes controlled on a mental level. CVS is dead, SVN is not. For most small teams, SVN is just a shortcut for the common workflow one would do with git, except for one little thing: you commit locally, and publish as needed.
Mercurial, or any DSCM, is great for detaching the act of committing work (accepting it as a valid step towards a goal) from the act of publishing work (putting your modifications up for other parties).
I prefer Mercurial over Git for the polish and supporting the anti-”linus is god” movement. I really didn’t like the way I was told he dismissed the idea of using incremental logs. I’m not being an extremist, or i would use Codeville.
I was writing some DB-access-intensive Python application and felt the need to cache function results. After fiddling with some dictionaries, I felt there was some underlying pattern I wasn’t spotting. Then it hit me. I was just memoizing function calls.
So I came up with this decorator.
import functools
import cPickle
def memoize(fctn):
memory = {}
@functools.wraps(fctn)
def memo(*args,**kwargs):
haxh = cPickle.dumps((args, sorted(kwargs.iteritems())))
if haxh not in memory:
memory[haxh] = fctn(*args,**kwargs)
return memory[haxh]
if memo.__doc__:
memo.__doc__ = "\n".join([memo.__doc__,"This function is memoized."])
return memo
Python is really easy to write.
23 August 2008 – Update: Corrected the bug pointed out by John. 25 August 2008 – Update: Improved as per reddit comments‘s suggestions.
Chandler always looked promising. I was really happy when I heard 1.0 just came out. Because I hadn’t my laptop around, I tried the web version and felt ok with it.
But that was my last step in my trail of Chandler faith. As soon as Chandler Desktop booted up, I was greeted with a soft, warm and fuzzy python exception: “Hey! This function receives one argument, you gave it two!”. Never good.
Tried to report the bug. Need a login for some bugzilla somewhere. Hmm, guess I’ll pass.
And don’t think that I am saying that there is no place for optimization, that is not true, there is just less room for optimization in the source itself, but there is lots of room for optimizations in terms of overall system performance and in terms of developer productivity. It is more important to focus on the big picture and solve performance problems that are system wide, or refactor code so that changes can be made much faster, than it is to solve a performance problem in a single line of code…unless of course that line of code is being called 8 million times by 50 parts of the system.
So next time you go to write a super clever line of code, think to yourself “Will the benefits of this super cleverness be outweighed by the future issues in maintaining and understanding the code?” And if there is any hesitation at all, then you better not be clever, because 3 months from now you will come across that code and say “What the hell was I thinking?” Then you’ll end up rewriting it anyway.
It’s quite correct, except for one little detail: “Then you’ll end up rewriting it anyway”.
I wish! Doing it right the first time is the good solution, but rewriting it when you latter come across it and realise it’s stupid is a “not good, not bad” solution. The problem is when you just can’t rewrite that piece of crap! Maybe you can’t test it, maybe you have something more important to do, maybe you don’t really understand it, maybe maybe maybe…
I could segway this into the perfect TDD and “Tests as a living, runnable spec” pitch, but I’ll let it rest.
I’ve been using MySQL more than what I would like to. In these endeavors, I’ve always felt the need for one thing: Negated joins. For example, in a many-to-many, I want to know what categories a post is not linked to.
For those who had similar problems, I present you two solutions: