Sunday, March 29, 2009

Something Rotten at Apple...?

Are you an iPhone developer? Do you want to be an iPhone developer?

Here is some bad news. The Apple App Store refund policy could cost you more than you think.

If someone buys your app, and decides within 90 days that they want a refund... Apple will refund the full amount to the user, and ask you, the developer to pay that full amount back to Apple, including the commission Apple took from the original purchase.

On the surface, this looks rather evil. However, it could help stem the tide of trash apps which are flooding the App store.

Thursday, March 26, 2009

Ladies and Gentlemen, prep your engines.

The next GameJam is starting on May 1st, 2009.

Registrations will open soon. Site upgrades are imminent.

Wednesday, March 25, 2009

I need a Scuzzie.

Scuzzies sound incredibly useful.

I can't find anyone that sells them though. :-(

Thursday, March 19, 2009

Tuesday, March 17, 2009

Mimicking Exceptions in Fibra

When a fibra schedule is running, a task can yield a sub task and pause until the sub task completes and returns a value to the parent task.

This works well, however, when an exception occurs in the sub task, the parent task does not receive the exception. This is a real pain, and breaks my normal thinking about exception handling. When using normal function calls, the exception should always bubble up the stack until it is handled. Fibra should provide the same behavior for sub tasks.

Well, now it does. Snippet below.

import fibra

def sub_task(x):
if x < 5:
yield fibra.Return(x**x)
else:
raise ValueError("x must be < 5")

def main_task():
# launch a sub task
# wait for it to finish and collect the result.
x = yield sub_task(4)
print x
# the sub task will raise an exception here...
# yet the exception will bubble up to the parent task,
# just like a regular function call.
try:
x = yield sub_task(5)
except ValueError:
print "Oops, an exception occured."

schedule = fibra.schedule()
schedule.debug = True
schedule.install(main_task())
schedule.run()

>>> 256
>>> Oops, an exception occured.

These features will arrive with Fibra 0.0.11, which is coming Real Soon Now.

Wednesday, March 04, 2009

Scalability of Stackless, Fibra and Kamaelia

After my last post, I decided to benchmark the scaling properties of Stackless, Kamaelia, Fibra using the same hackysack algorithm.

Left axis is milliseconds.
Bottom axis is number of tasks * 100.
Green line is Kamaelia.
Blue line is Fibra.
Red Line is Stackless.



These are the results, using Python 2.6.1 to run Fibra and Kamaelia, and Stackless 2.6.1 to run the Stackless test:




These are the results when using Stackless 2.6.1 to run all the tests:




It's quite interesting to see that Fibra copes with 600000 tasks better than 500000 tasks in both sets of results. Strange.

Benchmarking Stackless, Kamaelia and Fibra

In the cooperative threading world, as far as Python goes, there are a few choices. Stackless is the most well known, I guess. Since reading this post, I've been itching to see how Fibra compares to Kamaelia and Stackless. Now that I've implemented 'channels' or as I like to call them, 'tubes' in Fibra, I can implement the Stackless hackysack benchmark, and finally get a direct comparison of task switching speed between Fibra, Kamaelia and Stackless.

Fibra results:
python timeit.py -n 3 -s "import hackysack" "hackysack.runit(10000,1000, dbg=0)" 
3 loops, best of 3: 227 msec per loop

Kamaelia Results: Using this code.
python timeit.py -n 3 -s "import hackysack" "hackysack.runit(10000,1000)
3 loops, best of 3: 2.41 sec per loop

Stackless results: Using this code.
python timeit.py -n 3 -s "import hackysack" "hackysack.runit(10000,1000, dbg=0)" 
3 loops, best of 3: 31.5 msec per loop

These benchmarks show that Stackless is 7x faster than Fibra, and Fibra is 10x faster than Kamaelia.

This is the code I used to benchmark Fibra.

import fibra
import random
import sys

scheduler = fibra.schedule()

class hackysacker:
counter = 0
def __init__(self,name,circle):
self.name = name
self.circle = circle
circle.append(self)
self.messageQueue = fibra.Tube()
scheduler.install(self.messageLoop())

def incrementCounter(self):
hackysacker.counter += 1
if hackysacker.counter >= turns:
while self.circle:
hs = self.circle.pop()
if hs is not self:
return hs.messageQueue.push('exit')
sys.exit()

def messageLoop(self):
while 1:
message = yield self.messageQueue.pop()
if message == "exit":
debugPrint("%s is going home" % self.name)
return
debugPrint("%s got hackeysack from %s" % (self.name, message.name))
kickTo = self.circle[random.randint(0,len(self.circle)-1)]
debugPrint("%s kicking hackeysack to %s" % (self.name, kickTo.name))
yield self.incrementCounter()
yield kickTo.messageQueue.push(self)

def debugPrint(x):
if debug:
print x

debug=1
hackysackers=5
turns = 5

def runit(hs=10000,ts=1000,dbg=1):
global hackysackers,turns,debug
hackysackers = hs
turns = ts
debug = dbg

hackysacker.counter= 0
circle = []
one = hackysacker('1',circle)

for i in range(hackysackers):
hackysacker(`i`,circle)

def main():
yield one.messageQueue.push(one)

scheduler.install(main())
scheduler.run()

if __name__ == "__main__":
runit()

Tuesday, March 03, 2009

Fibra grows Tubes.

Tubes are like pipes, but... different. Anyhow, Fibra 0.0.9 includes some new Tube classes for communicating amongst tasks.
import fibra

def a(tube):
print 'Pushing "a" into tube.'
tube.push('a')
yield None

def b(tube):
while True:
x = yield tube.pop()
print 'Received "%s" from tube.'%x

t = fibra.Tube()
schedule = fibra.schedule()
schedule.install(a(t))
schedule.install(b(t))
schedule.run()

How to Increase App Store Sales

Are you releasing an iPhone Game?

Jack show's us why you need to release a free demo version as well.

Popular Posts