Tropical Software Observations

16 October 2012

Posted by Jun Rong

at 3:16 PM

0 comments

Ruby Block vs Proc.new vs Lambda vs method(:func) Summarized

There are many ways to pass code around in Ruby, so today I'm going to make a comparison between the 4 different ways. The first section, I will show the syntax of using each of them:
1. Block
2. Proc
3. Lambda
4. method(:func)
On the second section, I will compare the subtle differences they have.

A quick syntax comparison:
* note that the result is at the last section of each code *
1. Block
2. Proc.new
3. Lambda
4. method(:some_method)



Discussion on the subtle differences:
The table below summarizes what each of them can and cannot do, under the table, there are a more in depth explanation on the things shown in the table.
Description Block Proc Lambda Method Proof
Storing into a variable No Yes Yes Yes See (a)
How they work N/A Code Replacement Method Call Method Call See (b)
What class they belong to Proc Proc Proc Method See (c)
Check for correct number of argument No No Yes Yes See (d)

(a) Storing into a variable
Only block is not able to be stored into a variable, the rest is possible, refer to the quick syntax section above.

(b) How they work
Referring to the code right above this sentence, we can see that for proc_return, the line return "proc2 I AM HERE!" is never executed, this is because, Proc.new{return "proc1}.call works like code replacement, we can imagine proc_return to be like this:

(c) What class they belong to
Run this code: (d) Check for correct number of argument
Block and Proc don't check for the correct number of arguments, they discard extra parameters silently.(http://www.ruby-doc.org/core-1.9.3/Proc.html#method-i-call). For lambda and method(:func), they give error right away. Here's the code
For block:
For proc:
For lambda:
For method(:func):

06 September 2012

Posted by Huiming

at 9:07 AM

0 comments

Labels: , ,

Breaking ARC Retain Cycle in Objective-C Blocks

In a recent client project, we noticed its iOS app often received low memory warnings. The iOS app is developed with ARC-enabled (Automatic Reference Counting).
When profiling the app using Instruments > Allocations, we found that a lot of unused ViewController objects were not being released from memory.

Retain Cycle

The codebase uses a lot of Objective-C blocks as shown below, and self is often being called within the blocks:




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@interface DetailPageViewController : UIViewController
@property(nonatomic, strong) UIButton *backButton;
...
@end

@implementation DetailPageViewController
@synthesize backButton;

- (void)loadView {
  ...
  [self.doneButton onTouch:^(id sender) {
    [self doSomething];
    self.isDone = YES;
  }];
}
...
@end

In this example code, the controller object holds a strong reference to a doneButton object. But because the doneButton onTouch: block is referencing self, now the button object holds a strong reference back to the controller object.
When object A points strongly to object B, and B points strongly to A, a retain cycle is created, and both objects cannot be released from memory.

Use Lifetime Qualifiers

Apple Developer’s guide on ARC transition suggested a few ways to break the retain cycle using different lifetime qualifiers. It is definitely a must read for iOS development.
If your app is targeted for iOS 5, you can use the __weak lifetime qualifier to break the cycle:




1
2
3
4
5
6
7
8
9
10
@interface DetailPageViewController : UIViewController
- (void)loadView {
  ...
  __weak DetailPageViewController *controller = self;
  [self.doneButton onTouch:^(id sender) {
    [controller doSomething];
    controller.isDone = YES;
  }];
}
@end

Because we are using the __weak qualifier here, the doneButton onTouch: block only has a weak reference to the controller object. Now, the controller object will be released from memory when its reference count drops to 0.

13 June 2012

Posted by Yasith Fernando

at 3:14 PM

0 comments

Message Queue Implementations Reviewed

Message Queue Implementations Reviewed

After Googling around a while, I decided to look at the following message queues. This list was selected based on factors such as support, community size/activity, and feature set. It is by no means an exhaustive list.

Terms and Definitions

Most of the message queue implementations above make use of the following terminology.

Jobs

Tasks that are queued for processing. For example, if you want to send an email you would enqueue the email for future processing by a worker. This is a job. It has all the information needed by the worker to process it. In this case, we're talking about things such as recipient address, subject, body, etc.

Workers

Modules of code that handle the processing of jobs. A worker will fetch jobs from a queue and process them. In the email example above, a worker would grab the job from the queue and process it by sending off the email.

Delayed::Job

  • https://github.com/collectiveidea/delayed_job
  • This is a quite simple solution that will address the needs of 80% of developers out there
  • Delayed::Job was initially extracted from the Shopify.com codebase and was used by Github before they moved on to Resque
  • Delayed::Job stores its jobs in a table in your database
  • You can write jobs by extending a class provided by delayed_job
  • I find it to be a good solution if you need something very simple
  • Delayed::Job polls your database periodically for new jobs which is is not ideal but should not be an issue for most use cases
  • You can prioritise jobs and set the number of maximum retries per job. 

Starling

  • https://github.com/starling/starling
  • Starling was extracted out of the early Twitter codebase
  • Uses the memcached protocol
  • Jobs persisted to filesystem, so no database dependency
  • Lightweight
  • You need to write your own workers to perform polling and job execution
  • Polling means that Starling will be a bit slower than other queues such as RabbitMQ 
  • Last update 1 year ago

ActiveMQ

  • http://activemq.apache.org/
  • Mature, stable product that has been used by a lot of folks for some time
  • A top-level Apache project 
  • Can use the STOMP gem if you want to implement your own thing
  • Or use ActiveMessaging from ThoughtWorks 
  • Evented
  • Comes with a basic monitoring interface

RabbitMQ

  • http://www.rabbitmq.com/
  • Uses AMQP (advanced message queueing protocol) 
  • Written in Erlang 
  • Mature and one of the more well known message queues around 
  • Has lots of features, including file streaming 
  • Tons of clients/libraries for most of the major languages: http://www.rabbitmq.com/devtools.html
  • Fast 
  • Evented

ZeroMQ

  • http://www.zeromq.org/
  • Minimal, lightweight messaging framework 
  • No central server 
  • Ultra fast
  • Focused religiously on transporting messages between n points and nothing else 
  • Quite different from other MQs to the point where it's questionable as to whether ZeroMQ is a message queue or not :) 
  • If used to solve the email example mentioned above, the programmer will most likely have to handle the serialization/deserialization of the email, implementing of a daemon that runs in the background to receive email jobs, process them, handle retry logic, etc. 
  • Basically if you use ZeroMQ, you will have to reinvent some things that are provided out of the box in some of the solutions mentioned above
  • ZeroMQ is not meant to be RabbitMQ, Resque, etc. 
  • It does one job and it does it perfectly

Resque

  • https://github.com/defunkt/resque
  • Developed by Github for their internal use 
  • Uses Redis internally and Redis is super fast 
  • Feature rich 
  • Persists jobs to redis as json 
  • Comes with a rich Sinatra app that provides insight into what's happening with any queue
  • Not evented 
  • Popular within the Ruby community 
  • Well supported, stable, and well tested 

Conclusion

After going through the material I found online about the message queues listed above, I would use Delayed::Job for anything trivial, mainly because I have experience using it and it just works for most day-to-day tasks I've come across.

For use cases with high load and a need for stability, I would feel more comfortable going with Resque. It seems to be fairly straightforward to use and is quite popular so it enjoys good support from the community. Github uses it! And to seal the deal it seems to have the best management interface for monitoring queue internals. This is especially relevant since many message queue servers don't provide a query DSL, as databases typically do.

For instances where high performance and throughput are paramount, I would explore ZeroMQ. It almost certainly requires more work to get up and running (e.g. you'll need to implement most things needed for handling a message queue), but it offers great flexibility and speed.

If supporting multiple languages is a concern, RabbitMQ, ActiveMQ, and ZeroMQ get the nod due to their library availability for most popular languages and platforms.

19 January 2012

Posted by Teo Choong Ping

at 9:44 AM

0 comments

1st Singapore Clojure Meetup



Very interesting meetup last here at the Favorite Medium Singapore office. So much was discussed and I can say everyone left the meetup the wiser (in terms of Clojure knowledge). Here are some pictures from the meetup last night. If you are hacking Clojure in Singapore, you should definitely join our next meetup. Find out more about Clojure Singapore here.