How to make your django app slow

Mar 05 2012

The task every developer fears “Hey, I sometimes get a timeout when I want to see the last gazillion days of activity in the dashboard. What gives?”

Nikon GP-1 GPS Unit Test

Nikon GP-1 GPS Unit Test (Photo credit: AndyRamdin / ND-Photo.nl)

This problem started happening for a project I work on a few months ago. Through a lucky sequence of events I was able to push the problem back a couple of months … mostly just a beefier VPS on amazon with a bit more memory.

Yesterday I finally cleaned up everything else from pivotal tracker and was left with only that one dreaded item. That … slowness thing. Have you ever tried speeding up the execution of something when 80% of the codebase isn’t yours?

Context! I need context!

Let me give you a bit of context for what’s going on:

  • the project lets customers have many users
  • users enter events when they do stuff
  • the entries can be checked in a dashboard
  • there is a date-range picker to see more than just today’s events

And that’s where it all gets ever so slightly weird. When you choose anything other than today things start becoming increasingly slow and sometimes certain browsers decide that it’s just too slow and timeout.

No, it isn’t slow enough to cause the 30 second socket timeout.

No, caching wouldn’t really benefit this activity either.

A simple benchmark

In light of what I’ve learned about unit testing being for lazy people last week, I decided to set up a unit test that is actually an integration test and most likely isn’t either of those since it’s some sort of benchmark.

But it goes in django‘s testing framework, the python module behind that is called unittest, so I’m calling it a unit test.

    def test_date_range(self):
        t1 = datetime.now()
        response = self.c.post('/accounts/dashboard/',
                               {'dateFrom': (datetime.now()-timedelta(days=356)).strftime("%m/%d/%Y")})
 
        t2 = datetime.now()
 
        self.assert_((t2-t1).seconds < 2, "Too slow")

See, simple test. All it needed was exporting the whole production database into a fixture so django loads it up every time the test is run and then cleans up after itself.

The results are abominable! To return a dashboard with 250 rows of entries, this django app takes between 5 and 8 seconds. Clearly way way too much time!

The fix?

Indexes! Yes, adding an index where appropriate should speed things up immensely. Right?

U.S. Marine Corps SSgt. R. McIntosh, an engine...

Image via Wikipedia

Nope.

Creating indexes didn’t even put a dint in that benchmark. There was more fluctuation from the effect of memory pages on mysql’s performance. And anyway … what was I thinking really, indexes helping queries with less than 1000 rows of results? Don’t be silly Swizec.

Now what?

Added a bunch of “spent time” prints in the code and realized that even though it takes less than a second to make everything ready it then takes five seconds to render the template.

Wait what! Five seconds to render the template!?

Oh right … django’s querysets are lazy. That would probably explain it. The template is where those querysets get evaluated, they ping the database and that’s the explanation I’m looking for. It must be!

Except it wasn’t. Due to the way the view is written all the querysets get iterated over before the template is rendered. And they all have that magical select_related so all the fields getting accessed inside the template can’t possibly be triggering more db queries can it?

Well … no.

The main module has a function added that returns the latest related object. This function, correctly, only gets called once per rendering for every model.

But the function returns a queryset.

That queryset is lazy and it gets evaluated every single time that related object is used, which turns out to be 30 times per displayed row. But can 30 queries explain the slowness in rendering? Or should it be even slower if my theory was in fact correct?

I don’t know, but right now I’m working on a fix to make sure that object is solidified and is not a lazy queryset before it gets pushed to the template. If it works, great … otherwise I have no idea what I’ll try next.

user.get_profile() also gets called awfully often. Wonder how that baby works …

Enhanced by Zemanta

2 responses so far

A Google phone interview

Mar 02 2012

Yesterday I had my (hopefully first rather than last) technical interview with Google UK.

Short story: That stuff is fun! Longer story follows.

Google London HQ

Google London HQ

Sometime in January one of Google’s recruiters sent me an email; whether I’d be interested in talking with him. That my online profile looked interesting and so on … at first I almost dismissed it as spam – surely they send these out by the hundreds every day?

But hey, nothing to lose if I reply, right?

After I changed the agreed date of our video chat a couple of times – even forgot to respond to an email for two weeks – we finally got together. That was just your run of the mill blahblah with an HR person. What kind of stuff I like, what Google is all about, the fact they have shiny new offices in London and are looking for people to fill them with and so on.

Mind you, I don’t know whether I actually want to work for Google. They’re a huge company and working for them would fly right in the face of my principle to only work with startups! On the other hand, just being able to say I’ve worked at Google, even for a short while, would look incredibly well on my CV.

But hey, no sense worrying about this stuff until they offer me a job. Fuck it, let’s give the interviewing process a shot – looks like an interesting challenge anyway. Challenge accepted, I want to win.

They agreed to give me a call a month later, when I’d be done with exams. Yes, Google is in fact that nice. No rush, whenever you have time, you don’t want to even consider working before September? Fine with us. Please just let us talk to you kthxbai.

Yesterday was a month later.

The interview

Funny thing is, Google goes to great length to put you at ease about the whole process. They’re nice to you, send you friendly sounding email and at the same time everything looks so bureaucratized you can’t help but feel ever so slightly nervous.

There’s even detailed instructions for making sure you can be called via GTalk!

Google London HQ

Google London HQ

And the email says don’t you dare type on your laptop, the interviewer will hear you! Of course the interviewer spent the entire conversation happily clickety-clacking away at his laptop … it is in fact slightly annoying.

Andrew was a cool guy, very good with asking cool questions and letting me run amok – undoubtedly making an arse of myself several times when I climbed into a wall trying to explain a concept I introduced to the conversation and then backtracking to where I still made sense and trying to explain it differently.

The conversation had a light structure, felt like having a technical chat with a friend over some drinks:

  • describe a cool recent project, go into the technical nitty gritty
  • what’s an exception and how does it work
  • what is a memory leak and how would you go about debugging it
  • automated testing! talk, go!
  • write some code to create powersets
  • how would you look for a file containing a keyword in a deeply-ish nested directory structure

I have no idea how well I answered the questions … you know how these things are, you can explain at great detail what you think something is and how it behaves. But you might well be completely wrong.

The funniest part was after I explained a recent project (time-series analysis for predicting how much money I’ll have in two weeks) and Andrew’s response was something along the lines of “Oh that’s really cool! Do you have any plans on making it into a service? … wait, I’m interviewing you for Google …”

He seemed a bit confused.

Another interesting moment was when I was explaining memory leaks. He was looking for an answer inside the Java or C++ world (even made sure I knew them beforehand) and instead I explained that a cool way of getting memory leaks with javascript is through closures that are left hanging. I did also give the answer he was looking for, but off-handedly.

That somehow sent me into a long explanation of what closures are and how the concept is neatly related to continuations and function curling. And what those are. He generally let me wander around with my answers, probably trying to poke into what I do know and what I don’t, even if it’s beyond the scope of specific questions.

Coding under pressure

There was some coding involved – a very simple task. What is a powerset, blah, yes you got it. Now code something in your favorite language to turn a set into its powerset.

Google London HQ

Google London HQ

Not even in my worst nightmare could I imagine coding live, with somebody looking directly at my output, would be so difficult! It’s amazing, you go there and you think ah! yes, I know this! This is simple stuff!

You start … nothing.

I spent four or five attempts climbing myself into a wall and deleting all my code before finally producing a cool looking algorithm – a lovely non-recursive solution; simply because I couldn’t think of a recursive solution, just knew that the simplest solution is supposed to be a recursive algorithm.

def powerset(set):
      binaries = [bin(a) for a in range(2^len(set))]
      power = []
      for yeses in binaries:
        subset = []
	yeses = str(yeses)
	for i in range(len(yeses)):
                 if yeses[i] == “1”:
        		subset.append(set[i])
	power.append(subset)
      return power

This is whiteboard python. The syntax for calculating a power is wrong and I’m fairly certain bin isn’t an actual function in standard library. I’m also not sure converting a binary number to a string works quite as I envision it here, might need to use “%d” % blah syntax.

But the general idea is simple: take all binary numbers from zero to the powerset’s length, iterate through them and use digits as binary switches for picking elements to put into each subset.

Google 的貼牌冰箱(Google refrigerator)

Google 的貼牌冰箱(Google refrigerator) (Photo credit: Aray Chen)

It took me forever to deduce the formula for calculating the size of a powerset from first principles. Couldn’t remember it. Looked at the examples I generated in my head … “Ok, so every time you add an element, you double the size of the powerset. n^2 … no that’s not it … could it possibly be 2^n? Damn it! yes, that’s it!”

But Andrew reassured me he loved the solution even though it needed a bit of fixing; and you can obviously see that’s not the most elegant python code out there.

And now we wait

In general I think I managed to convince Andrew that even though my explanations often came with a “I haven’t looked into how this works exactly, but here’s my understanding of what should be going on” I know a fair bit about technology and if push came to shove, I could code my way out of a wet paper bag to save a life.

If he got the same impression, the next step is a full day of back-to-back technical interviews at Google’s London offices.

First though, we wait for “my” recruiter to get back to me about how the phone conversation went.

Enhanced by Zemanta

11 responses so far

I’m a pro blogger now!

Mar 01 2012

Late January @andraz approached me with an idea: What if I helped Zemanta spruce up their tech blog?

The blog had been languishing in neglect for a long time. An update every couple of months, completely random and with no real direction or purpose. Since they’re a company that’s all about blogging I guess it didn’t look good to have a dead blog on their domain …

Now, I’d never blogged professionally and the whole prospect seemed a bit scary at first. It’s one thing to arse about on your own blog and something completely different to ask for money and then be at a loss for words.

Post stats

Post stats

The arrangement is pretty simple: Zemanta provides cool stories – I write two posts a month and whore them out on appropriate social networks.

Two posts so far and everything went better than expected!

The first got about four thousand pageviews to a blog that was previously getting ten people a day. The second post got about 15,000!  Smashing success! And I actually think the score could be a lot higher had their server not melted.

It wasn’t easy though, each of those posts took four to five hours of research and writing – and that’s not even counting the work it took to build my writing to where it doesn’t smack people in the face and make them leave (too much)

But the research is most fun!

I get free range to pick developer’s brains, pretend I understand what the hell they’re talking about, then spend hours getting up to speed online and in the end dump that research into a story. And it does have to be a story!

Nobody wants to read a dry technology report … well, some do, but they aren’t deterred by a good story … And there’s just enough Thompson in my blogging that I keep referring to Zemanta in the third person on their own blog; which looks a bit weird.

Honestly, it just makes me giggle like a school girl that anyone would pay me to write blogs. It’s marvelous!

 

Enhanced by Zemanta

3 responses so far

A talk that changes everything

Feb 28 2012

This talk by Bret Victor has changed my entire perspective on programming and how I want to continue working in this field. It starts out a bit slow, but you should watch it. Well worth it, I promise.

Bret Victor – Inventing on Principle from CUSEC on Vimeo.

A quick recap of the more salient points for all you lazy bastards out there who aren’t willing to devote an hour of your time to expanding your horizons.

1. To be creative, you need an immediate, direct connection to what you’re doing, none of that “several layers of abstraction on top of abstraction and thinking ten steps ahead to understand what’s going on” … why would you have to emulate a computer in your head when you have one right there?

2. When inventing new things, perhaps we shouldn’t be thinking about creating cool products or hacking the awesomest algorithm or even the most elegant design both in code and UX – perhaps we should find a principle and stick to it? Once you have that principle, everything else follows.

3. There are some extremely awesome demos in that talk. If nothing else, at least skip around to those – there’s an epic way to make games, an awesome way to create animations and a pretty cool way of visualizing what your algorithm does as you write it.

There isn’t much more I can add to all this, just watch the video and be amazed. Now excuse me while I run off to find my principle.

Enhanced by Zemanta

2 responses so far

Unit testing is for lazy people

Feb 27 2012

The other day I was talking to a guy about a possible freelancing gig and he said how wonderful it was that I should bring up the topic of unit/automated testingwithout being asked. Said that most (many?) developers don’t have the level of rigor to use automated testing.

Oops building

Oops building

My reaction was one of disbelief “Rigor!? But automated testing is one of the laziest things a developer can do! It speeds stuff up so much!”

As luck would have it, last night I was hit over the head with my own words and nearly died debugging a single function.

I was working on Stripe webhooks and for security reasons decided not to use the event data sent in request body. Makes sense right? Take the event id from request body, then fetch the actual event from Stripe.

It’s the only way to be certain you aren’t responding to bogus events sent by an evil person trying to make you look bad (nothing actually bad can happen, at worst a customer would get extra paid invoice emails).

Due to poor decoupling – I didn’t really want to decouple a 6 line function into two functions – everything was now difficult to test. I can’t create events on Stripe’s servers with unit tests and without actual events existing I can’t test the function works as it’s supposed to.

How many bugs can you put in a 6 line function anyway?

A lot of bugs!

When the client tested on staging … it didn’t work. Invoice email wasn’t sent and Stripe complained of a 500 error.

English: British Army Signals Trials Unit test...

Image via Wikipedia

It took me almost two hours to fix all the bugs because my testing cycle looked like this:

  1. change code
  2. commit to develop branch
  3. switch to staging branch
  4. merge develop branch into staging
  5. push to github
  6. change to other terminal window
  7. pull from staging branch
  8. restart python processes
  9. go to Stripe dashboard
  10. pick customer
  11. create invoice item
  12. create actual invoice
  13. choose invoice
  14. pay invoice
  15. go to Stripe logs
  16. find invoice.payment_succeeded webhook
  17. scroll down to response
  18. look through raw html of django’s error page
  19. find symptom
  20. GOTO 1.

That’s right, a whopping 20 step debug cycle all because I’m an idiot and couldn’t find a way to automate this. Or maybe I was too tired to do the unobvious thing … although I still don’t want to split a 6 liner into two functions.

With proper unit testing the debug cycle would look like this:

  1. change code
  2. run tests
  3. symptom thrown in face
  4. GOTO 1.

Much lazier right?

For the record, those six lines of code contained 4 bugs ->

  • forgot to import a module
  • different event data structure than I understood from the docs
  • twice^
  • misnamed variables from one line to another

Yes, all of those could easily have been caught if my test coverage was actually any good! And then not only would I not look like an idiot in front of the client, I’d probably spend no more than ten minutes fixing this.

Let this be a lesson both to you and to Future Swizec!

Enhanced by Zemanta

28 responses so far

The commonest javascript bug

Feb 24 2012

CAEN 25th Anniversary Celebration

CAEN 25th Anniversary Celebration (Photo credit: rosefirerising)

Every couple of weeks somebody will come running to me: “Swizec, Swizec, I did everything right, but this javascript isn’t doing what it’s supposed to! Whatever I click only the last item works. Halp!”

Every time it’s the same bug – people just don’t understand how loops and closures play together in javascript. Invariably they loop through an array, attach the index to an event, then get frustrated when, upon triggering the event, that particular variable seems to have the wrong value.

The code usually looks something like this:

json = JSON.parse(this.responseText);
for (i = 0; i < json.links.length; i++) {
       params = json.links[i];
 
       row = $$.ui.createRow({
                 // use params for settings, it works
                 click: function () {
                    var modalBrowser = new MiniBrowser({
                                        // it all breaks down here
                                        url: params.url,
                    });
       });
       // do some other stuff
}

Can you spot the problem?

On the first use of params everything is happy, using the local variable, which is updated on every loop iteration. But when that click event is triggered it still uses the local params variable … that was updated on every loop iteration.

By now, the loop has long since completed and that variable holds the last value – causing a weird-looking bug that is difficult for newbies to fix because, hey, why should I know about how pointers work? This is a scripting language damn it!

Luckily the fix is very simple:

json = JSON.parse(this.responseText);
json.links.map(function (params) {
 
       row = $$.ui.createRow({
               // use params for settings, it works
               click: function () {
                    var modalBrowser = new MiniBrowser({
                                   // it magically still works here
                                   url: params.url,
                    });
       });
       // do some other stuff
});

Just change the for loop to a map and you don’t even have to fix anything else. Everything works as usual, except now all the code is wrapped up in a closure and caries a reference to the whole variable scope around. Simply put – when the click event is triggered all the variables that were known when it was set are still there, with exactly the same values.

Generally speaking, even a modest understanding of closures (like I have) will make it much easier to write javascript. Might even help you fix a memory leak or fifty.

Enhanced by Zemanta

One response so far

I made a steampunk costume

Feb 23 2012

Every couple of years I actively participate in our version of mardi gras and dress up in a costume. It’s usually something mundane like dressing up as a living statue or a girl or whatever.

Full costume

Full costume

This year, however, I decided to go full out. Finally, an excuse to make a steampunk costume!

I’m not the handiest person in the world so the whole thing was a bit of a mess – not a single straight cut anywhere, parts of my room are now gold and there is trash everywhere. But I had a lot of fun working manually for two days. It’s remarkably refreshing to do something in meatspace now and anon.

All the manly work even made my fifth chest hair grow! Score!

I’m quite pleased with the result, the costume turned out pretty decent and only cost about 30 euro in parts and another ~300 euro in time. Plus whatever old crap I found collecting dust around the house; like for instance, bits of my high school death metal outfit.

It begins with a pile of junk

It begins with a pile of junk

Regular welding glasses from a store, just added the fluff

Regular welding glasses from a store, just added the fluff

First stage of shoulder armor - an old belt, strip of cloth and leather tied on with aluminium wire

First stage of shoulder armor - an old belt, strip of cloth and leather tied on with aluminium wire

The hat is actually something I always wear

The hat is actually something I always wear

Normal welding gloves and some wire

Normal welding gloves and some wire

Took several tries to make symmetric wings

Took several tries to make symmetric wings

The trick is to apply copper paint with a sponge

The trick is to apply copper paint with a sponge

Armor panels

Armor panels

The finished shoulder armor drying

The finished shoulder armor drying

The gloves turned out quite well

The gloves turned out quite well

Manliest my desk has ever looked

Manliest my desk has ever looked

Slightly bigger picture of full outfit

Slightly bigger picture of full outfit

Unfortunately the costume did not prevent me from accidentally getting way too drunk at the party. Lost my real glasses, the hat, my keys, even my moleskine.

All in all, the most expensive party I’ve ever been to … but at least the costume is cool :)

Enhanced by Zemanta

Comments Off

FANN – neural networks made easy

Feb 20 2012

Convergence!

Convergence!

Over the weekend I was struck with the realization that I don’t know how to use neural networks in practice, damn it. Even though a few months ago I realized what neural networks are, even though I’ve tried implementing them, even though I’ve used them in a class setting …

How the hell do you use these things in real life!?

Implement from scratch? … no that can’t be it.

Find a library, write some code, run some tests, fiddle with features, run a test, fiddle with features, realize everything is slow, decide to use more layers, fiddle with features, play around with activation functions, run a test, fiddle with features, rewrite the code because it’s a mess, fiddle with features, run a test, run the network, run more tests and so on and on ad nauseum.

That can’t be it either …

FANN

Looking far and wide for a good library to use I stumbled upon FANN – Fast Artificial Neural Networks.

Fast Artificial Neural Network Library is a free open source neural network library, which implements multilayer artificial neural networks in C with support for both fully connected and sparsely connected networks. Cross-platform execution in both fixed and floating point are supported. It includes a framework for easy handling of training data sets. It is easy to use, versatile, well documented, and fast. Bindings to more than 15 programming languages are available. An easy to read introduction article and a reference manual accompanies the library with examples and recommendations on how to use the library. Several graphical user interfaces are also available for the library.

Perfect!

Not only has someone gone to the trouble of implementing everything and making sure it works – nothing sucks more than figuring out whether you’re using your learning software wrong or it’s just buggy – they even gave it all the fiddly features I need!

It gets better! There’s a slew of graphical interfaces -> You get to play with the fiddly bits without even knowing what you’re doing! Yes!

Put the data in the fann format, load it up, and away you go. Playing around until you figure out what you’re looking for, then you can just implement the same thing with the FANN binding of your choice.

It can suggest a good training algo

It can suggest a good training algo

You get to set up the neural network

You get to set up the neural network

Fiddly bits!

Fiddly bits!

Watch it converge in real time

Watch it converge in real time

Done in a few hours

FANN really saved my skin last night. At least the GUI did. I still haven’t solved my problem – trying to predict how many people will read a whole post – but it took me literally a couple of minutes to realize that the same network can’t be used to predict two outputs since it won’t even converge.

That’s something very specific to the problem.

I also realized the networks were overfitting my data, then performing poorly on the test.

Another specific thing.

It is because of this incredibly problem-specific nature of most work involving neural networks that having tools like these is really important. Who wants to fiddle around with implementing all this stuff by hand for several hours before even running the first tests?

I probably ran twenty or thirty different configurations in the space of three hours last night. Could I have done that without a simple tool? Probably not – wouldn’t even have the first configuration implemented by now.

Now if only the GUI tool calculated precision and recall instead of mean standard error …

Enhanced by Zemanta

5 responses so far

I walked all over a lake!

Feb 18 2012

You’ve heard of Lake Bled right? The only lake in Slovenia containing the only island in Slovenia? Right!? Oh it’s just one of the most beautifulest places in Slovenia.

Lake Bled

Lake Bled

Yesterday I walked all over the bad boy!

The really amazing thing about Lake Bled is that every couple of years it completely freezes over. To the point you can take a walk right up to the island and endure one of the biggest brainfucks possible.

Every fiber in my body fought against that first step. There you are, standing on the shore and … you take another step. And it works. You’re on water. It’s a lake. And you’re standing on it!

Then you take a nice long walk to the island – about a kilometer and a half one way. The whole thing is just profoundly weird.

Being out there in the middle of the lake isn’t too strange, feels kind of normal until you look back and realize everything looks wrong. You’ve been coming here your whole life, but it was … different.

The way back is even odder. Land slowly inching towards you with every step you take and your brain slowly but surely realizing that something odd is going on here.

Then you have some delicious cake.

 

Lake walking

Lake walking

Shore view

Shore view

Looks like a polar expedition

Looks like a polar expedition

Looking back

Looking back

Castle Bled

Castle Bled

Moar ice

Moar ice

There was also a huge crack

There was also a huge crack

Not the usual view of Bled

Not the usual view of Bled

Island view to the other side

Island view to the other side

A random cyclist

A random cyclist

Finally, a swan

Finally, a swan

Enhanced by Zemanta

5 responses so far

Two business things Slovenia needs to change

Feb 15 2012

This post is aimed at my local readers, the rest can look at it as a curiosity from an awesome small country that is fumbling all over itself trying to be even awesomer.

Slave labor

We don’t have Mexicans, but we do have students. A whole social caste of people ripe for abuse because they don’t realize their worth and hey, what better way to keep operating costs low than to employ a bunch of these guys, pay them below-minimum wage and tell them it’s even worse elsewhere?

Students in the incubation room at the Woodbin...

Students in the incubation room at the Woodbine Agricultural School, New Jersey (Photo credit: Center for Jewish History, NYC)

Not cool!

Originally student work was invented to give students some degree of autonomy, to make getting through college cheaper and easier. It’s since been quite corrupted … whole companies running on nothing but slave labor.

My recent survey about how much money comp sci students make shows that most make less than 10 euro an hour, glaringly obvious even on just a cursory glance.

These aren’t internships mind you. A lot of them are full blown computer engineers, often-times making companies’ core products completely on their own or with a help of a couple other students.

It’s sickening.

Even worse is that when I published the survey, a lot of students pinged me and said “Hey, don’t you think you set the bar somewhat high? Most of us don’t even make the 7 euro lower bound you set up …”

No, for fuck’s sake no! This is money we’re talking about! You shouldn’t be paid how much everyone else is being paid, this isn’t some competition in fairness, this is cold hard cash! Demand to be fucking paid how much you are worth to the company.

I can (sort of) understand a waiter working for 4 or 5 euro an hour. But anyone paying less than 10 for any nongeneric type of service should be laughed out of business.

And business people … shame on you!

If you get a student who is any good and they timidly ask for 7 euro an hour because they consider that quite a bit of money. Tell them they’re being stupid and demand to give them 15 euro. Congratulations, you just earned an extremely happy and loyal worker. And it’s still cheaper than giving them full employment.

When paying students, always keep in mind they rarely work more than half-time. They need to make a living off this!

Speed of business

Another thing that really gets on my nerves in Slovenia is that everything is so slow. Sending an invoice to a client in Slovenia feels like sending it down a black hole.

Invoice, Chas M Stieff Manufacturer of Grand &...

Invoice, Chas M Stieff Manufacturer of Grand & Upright Pianos (Photo credit: Lynchburg College Archives)

The average response time I’ve experienced is … a long time. Hell, I am legally mandated to give you two weeks of time to pay up and most businesses are very very careful not to pay anything sooner than that. The problem is so big the only thing student unions do is make sure people get paid quickly by just fronting the cash.

I checked. There are invoices from a year ago that are still marked as “fronted by student union”.

Sickening!

You know what happens when you send an invoice to a proper country? You get paid the next day. Last night someone wired me the money literally 20 minutes after I clicked send on the invoice email.

Of course then I had to wait roughly 15 hours for my bank to actually process the transfer of a few electrons …

Conclusion

Slovenia is awesome and I love it to bits, but I sure as hell get the feeling it doesn’t want me here. And hey, the top of the crop of our entrepreneurs, businesses and pretty much anyone worth their salt … is leaving.

I wonder why.

PS: if looking at the data from that survey makes me any angrier I will hurt people.

Enhanced by Zemanta

11 responses so far

« Newer - Older »

« Possibly the ugliest python ever... I walked all over a lake! »