|al(j)ʊˈmɪnɪəm| mass noun - the chemical element of atomic number 13, a corrosion-resistant metal named after Habib Alamin, a computer programmer

My thoughts on Cassie Jaye's “The Red Pill”

I went to see Cassie Jaye's documentary, “The Red Pill”, a couple of weeks ago now (19 November, International Men's Day) with a friend and brother. This is less a review, and more me recounting my experience without spoiling the movie in any major way. Disclaimer: I backed the movie on Kickstarter.

I travelled out to London to see it. It was supposed to start screening at 6 o'clock in the evening, but there was a period of confusion for everybody for an hour and a half, as the film only started playing at 7:30. I'm not sure who was responsible for the screening, but that was a bummer (though not really a fault of the movie). I only mention it to make the point that if you're going to a screening, keep in mind that they're not all made equal. This was a really low-key venue situated in South East London. It was small and inconspicuous - not all that official. There was no Q&A segment, no appearances by Erin Pizzey, Cassie Jaye, or Warren Farrell, all of whom had attended other screenings.

Once we got past that hump, the movie began.

I guess the first thing I have to mention is that it did not go into a lot of the stories/interviews in the trailer, which I wasn't expecting. I still really enjoyed the movie, but I was looking forward to seeing some of those narratives expanded in the movie. There's a really moving part in the trailer where a man talking about his experiences suddenly stands up and is visibly upset, saying, “I don't like sympathy for any of this stuff”. That said, there were also parts featured in the movie that I know a lot of people (including myself) were hoping to see — such as the interview with Karen Straughan (GirlWritesWhat) — that weren't in the trailer. I really hope all the footage is released to the public some day. I think it could prove very valuable.

I think Karen Straughan really made palpable the hypocrisies of feminism with regards to language control. As always, she was very articulate and makes these connections that are clear after the fact, but few people think about before she points them out. She's very good at spotting distant inconsistencies, which is a skill I really appreciate.

I don't know what kind of footage we missed, but the stories that were shown were so compelling and infuriating (Fred Hayward's experience with losing his son comes to mind in particular). Overall, I think Cassie did really well with the editing.

I really enjoyed the video diaries, and I think they added an interesting and convincing dimension to the movie. The diaries offered a chance to see Jaye’s internal struggle with her own long-held beliefs. As the film progresses we begin to see her attempt to resist change and double-down on a feminist rhetoric as she realises she is losing a part of her identity. This will send a clear message to any feminist (or non-feminist) who watches the film, I hope.

There was a no-holds-barred scene when talking about one particular issue, footage that came as a bit of a shock, but I'm really glad she showed it. It really forces the viewer to be confronted with the unfiltered truth right in front of them. There was no warning, and an audible groan from the audience shows that it did its job.

I really enjoyed the video diaries, and I think they added an interesting and convincing dimension to the movie. The diaries offered a chance to see Jaye’s internal struggle with her own long-held beliefs. As the film progresses we begin to see her attempt to resist change and double-down on her feminist belief system by leaning on her friends and feminist groups as she realises she is losing a part of her identity. This will send a clear message to any feminist (or non-feminist) who watches the film, I hope.

There was a no-holds-barred scene when talking about one particular issue, footage that came as a bit of a shock, but I'm really glad she showed it. It really forces the viewer to be confronted with the unfiltered truth right in front of them. There was no warning, and an audible groan from the audience shows that it did its job.

After the movie, I stayed and chatted with members of the audience for quite a while. A lot of people there had already taken the red pill, which was quite disappointing to me, as it essentially meant the movie was just preaching to the choir. I had hoped for a bigger turnout by blue pill people, but I guess that's to be expected before the general release on places like Netflix, iTunes, Amazon, etc. That will be a big boon for getting the message to people who haven't heard about the issues, or even those that have, but have not yet come into contact with some of the case studies, statistics and arguments made in the film.

The movie wasn't made for people like me; it was a good primer into a lot of the common issues, but the rabbit hole, as they say, goes so much deeper. As someone who's been involved with the movement for a long time, mostly through regular donations and mostly anonymous discussion online and raising the issues whenever they are relevant offline (i.e., more advocacy than activism), I already knew about all of the issues raised in the movie, barring some individual interviewee's stories. I often want to start talking about some of the stuff you discover deeper in, and I think Cassie did a really good job tailoring this to people new to the issues (but obviously I don't say this from a noob's perspective).

As I said earlier, most people there were already red pill, but there was one person there (a self-proclaimed freelance journalist) who came in with opposing ideas about the movement to write an article about the movie. It's sad that I have to say this, but props to that person for actually going to see opposing ideas and staying behind to have a discussion, instead of just signing a petition to stop the screening. In the midst of the group discussion, some points they made slipped through the net, which I will take the time to address here. I gather they were a feminist, but I don't recall if they explicitly said so. I had a much more interesting and engaging conversation with the feminist than the other people there, incidentally. Listening to my own opinions echoed back to me has never been my idea of a good time.

The first thing was that a particular video diary looked really staged, and to be honest, I wouldn't entirely disagree. I had the same thought during that particular video diary while watching it. It seemed like less of a structured diary entry (which you'd expect to be planned) and more a recording that was supposed to look unplanned, but didn't. All I can say to that is that it's not really a counter to the issues raised and the validity of the arguments, and it's very subjective (and a low shot, but I think in good faith during a casual conversation). Cassie is a director, it's not unusual that she would keep high production value video diaries, and it's not unusual that a few of them would look staged as a result of that (and technically are, in a way).

The other thing the feminist mentioned was that the movie touched on the extreme rhetoric often employed by AVfM, the biggest men's rights site on the web (disclaimer: I am a regular donator), but never really addressed them. I would have liked to see more of that addressed too and give them a chance to defend themselves, just to show the all the ways in which a lot of feminists and the mainstream media try to twist and distort and take out of context what he says. Alas, that would take a whole movie in its own right, and probably not one a lot of people would watch by choice. They did address one article in particular, “Bash a Violent Bitch Month”, noting that it was a satirical response to a Jezebel article, “Have You Ever Beat Up A Boyfriend? Cause, Uh, We Have”, which I think is enough to plant doubt into people's minds about and trigger their own research. That said, it would have been nice to hear from Paul Elam directly, who was interviewed and have a quick 30-90 second explanation directly from the owner of the site.

The feminist also raised the issue of the movie seeming biased (noting the avoidance of challenging the extreme AVfM rhetoric as evidence for this). This movie is about one feminist's journey into the men's rights movement, who have an alternative perspective on gender issues. Cassie herself notes that she focused on the MRM as it has been so often ignored, maligned, and distorted by the mainstream media. That it focused predominantly on letting the people of that movement speak for themselves shouldn't be surprising, and is, I think, fair. Cassie did give some air time to feminists to speak too, as she should have, and there would have been more feminist voices had David Futrelle (and others) not declined to speak with her after his smear campaign of Cassie when he found out that she was becoming sympathetic to the MRM and that the movie wasn't going to be an attack on it.

The other thing pointed to as evidence of the bias is the focus on “baying crowds” of feminists juxtaposed with interviews with MRAs. As mentioned before, the film has a focus on the MRM's platform, as most everyone knows much more about the feminist platform than they do the MRM's. It's not like Cassie completely avoided the “extreme” things people like AVfM in particular have written. In fact, the movie opens with a bunch of really extreme headlines and article snippets from AVfM, and as I said, she addresses one of those articles later in the film which plants the first seed of doubt about previous feminist responses to them. Feminists were given a chance to speak as well. All Cassie did was document (as a documentarian should) the facts. If reality has a bias, that's not a failing of the messenger.

This bit has nothing to do with the film, but I have to address it because it's so funny how it whizzed right past me at the time. I started talking about the “violence against women” line and how violence is perpetrated much more against men, and how we often avoid perpetrating violence against women for the sole reason that the would-be victim is a woman. I talked about my experiences with violence as a man and how it's so normal that you don't even think about it as a problem, but rather as something that's just there that people try to avoid imposing on women. They started talking about how, after starting their transition to being a woman, they noticed a difference in the way people treated them, and in fact, they started being targeted for violence; they specifically mentioned an incident in which a stranger chased after them and called them a “fag”. I didn't even think about that little extra line, but looking back on the conversation later, I think their experience proves my point. Clearly, in the eyes of this person that targeted them, they were still a man (and in this case, they still spoke and (mostly) appeared to be a man). That the person shouted “fag” demonstrates that the person I was talking to was being targeted for being a homosexual man (whether they were or not is beside the point).

Anyway, to get back to the film, all in all, I think it's a great primer to the MRM for people who are ignorant of the issues and I really hope it gets wide distribution. I hope it opens up a wider discussion about men's issues, and the problems with feminism, some of it inherent. I think Cassie and the team did a great job, and I really want to thank them for putting their careers and personal relationships on the line to share the journey. I know Cassie has lost friends because of this movie, and I don't take that lightly. Thank you, Cassie! Thank you to her boyfriend for being willing to challenge her on her feminist beliefs.

I really believe this film marks a turning point in mainstream acceptance of MRM ideas. I think the excesses of feminism has accelerated this process and they only have themselves to blame. I have heard that several feminists have really been given pause after watching this film, and I hope that continues to happen.

Pitfalls to avoid when writing multiprocess Ruby code

So, a couple of weeks ago, I wrote a post on how fast forking can make your MRI Ruby code. There are a few things to be aware of, though, before you go out and take advantage of this.

Obviously, your code has to be thread-safe. I can't tell you if your Rails app is thread-safe or not, but this Bear Metal blog post might be helpful.

The first pitfall I experienced was ActiveRecord. If you fork, you must use a different connection per process. I cannot recall the exact error message that you would get if you did not use a new connection (and I no longer have access to the codebase to quickly check that, nor am I going to start up a new Rails app to check).

I was writing a short-lived process, and simply saying ActiveRecord::Base.connection.reconnect! in the fork block was fine, up until I needed to test the code with RSpec. Then, I had to change the process to disconnect from the main process, establish a new connection for each subprocess (in the fork block), and then establish another new connection in the main process, which I did after waiting for all the child processes to finish.

Speaking of waiting for child processes, the second pitfall was tricky. I used Process.waitall2 to indiscriminately wait for all the child processes. Of course, that was fine, since it was a short-lived process started from a Rake task, but once I needed to test that code, it started interacting with other code, some of which could also start their own child processes. In my case, we were using a gem called sunspot-rails-tester, which started a Sunspot process for integration tests. The problem here was two-fold.

First of all, Process.waitall2 was waiting for a never-ending child process to end. Changing that to simply Process.waitpid2 pid on each of my child process IDs fixed the problem with my test taking forever (literally) to finish until an outside force stopped them. That's a strike against imperative-style global variables (of course, there was no variable involved here per se, but this is analogous to saying Process.waitpid2 pid on each process ID in a global list of all child process IDs across the program).

The second problem was being unable to connect to Sunspot on some of the integration tests that we already had. This one was because of an at_exit hook that sunspot-rails-tester had installed that causes the child Sunspot process to be killed once the main process had completed to avoid an orphaned process. My child processes were inheriting this, so that when they completed their task, they were causing the Sunspot process to be killed. This was fixed by creating my own at_exit hook in the fork block that simply exited with the right status code (which is important), but using Kernel#exit!, which skips at_exit hooks, instead of Kernel#exit. at_exit hooks are called in the reverse order they are defined. We need our own at_exit hook because simply calling #exit! on completion doesn't account for exceptions.

The final thing I want to mention is that you may want signals sent to your parent process to be propagated to its children processes. This is easy to do: simply call Process.setpgrp, which “sets the process group ID of the calling process to the process ID of the calling process” (equivalent to setpgid(0, 0)). Child processes inherit the parent process' group ID, and any signals sent to a group ID are sent to all members of the group. This effectively means the parent process' group ID is set to its own process ID, its children inherit the group ID, and so when a signal is sent to the parent process, since the group ID is the same as the process ID, the signal is sent to the group, which is then propagated to all processes in that group (or “session”).

No doubt there's more that I missed, so please do let us all know if I've left something out.


If you're running a heavy task that can be split up into many independent tasks in a thread-safe manner (I'm assuming you have all those tricky details worked out or you're willing to work through them), you probably want to parallelise it.

Unfortunately, Matz' Ruby Implementation has a GIL that prevents more than one thread from executing at a time. It abstracts the OS' native threads away and uses a scheduling system to make sure that only one Ruby thread is running at a time (with a few exceptions that likely aren't relevant).


Not to worry, though. Ruby programs can fork themselves to create child processes, and since each Ruby process is independent, you can have as many threads as you like this way.

I knew that there were performance limitations to MRI due to the GIL, but I didn't realise just how much faster your code could be if you parallelised it. At work recently, I took charge of implementing a new system to handle vehicle images and consolidate all the different ways that we currently process images through our app.

Our users import a huge amount of vehicles through our app every day, and many of those have several images each. We calculated roughly how many images would go through our app every day and it was a large number (~100k at least), but we figured that could be mostly solved using Last-Modified and ETag headers.

The real problem was the initial influx of images that we'd have to migrate from a vehicle_pictures table to the polymorphic document_assets table that we already have in place for other models. We use Carrierwave.

I did a test run of ~800 images on our QA server and that took ~72 minutes. Evidently not good enough. Using ruby-prof, I determine that the majority of our time was spent in Carrierwave, in places we couldn't really do much about. I decided to have a look at parallelising the task and seeing how we could get it down.

My initial implementation got it down to ~20 minutes. Not bad, but then I noticed I had accidentally forked once for each image, as opposed to each batch. Well, damn! Even with all that overhead for each process, the improvement was pretty good. After another attempt, this time creating two processes for each core of the machine (some research online indicated that for IO-intensive tasks like this one, you want at least that much to make sure there's always one core doing something), yielded ~10 minutes.

The second thing I noticed from the profiling was that a lot of time was being spent in Excon (which Fog, written by the same author, uses, which Carrierwave uses to interface with S3). After benchmarking various Ruby HTTP clients, Excon turned out to be the slowest one by a wide margin. However, I did not deem it worth the work to write our own Carrierwave storage backend given the improvements gained by using the fastest one.

Luckily, our problems were not unique: I discovered a gem called carrierwave-aws that interfaces directly with aws-sdk, instead of Fog, and this brought our time down to ~4.5 minutes. I actually managed to get it down to ~2m37s, but retested with only the number of processes I knew we could afford in production, giving us our final ~4.5m figure.

My story is not over yet, though. Automated testing of the multiprocess code has come back to bite me. The previously happy test examples for this class no longer pass, though manual testing shows the same results as before. Parallel code can be tricky to reason about, but it can definitely be worth the payoff.


A couple days ago (on Friday), I gave a talk at work for Dev Forum on (data) types. You can find the Keynote slides here (with presenter notes), and the PDF here (again, with presenter notes).

It's been a while since my last Dev Forum talk, and I've kept meaning to do another one, so although this isn't the best talk on types (it's essentially a long introduction to types/a whirlwind tour of different typing systems, as opposed to why types are desirable, their benefits and tradeoffs, etc.), I'm really glad I gave it. I think I had a strong start, too, and I have learnt what to do and what to avoid for next time.

Truth be told, most of the work of actually putting the whole thing together was done on the last day, though the talk had been ruminating for a while now. It's a recurring theme now, I intend to put my talk together on the second week (Dev Forum is every fortnight), things inevitably end up being really busy, and I skip another week. I had promised to give this talk this week, though, so I couldn't break that. When I looked back on it later, I even realised I'd completely forgotten a slide on type inference (maybe next time, as I intend to flesh out this topic; it probably fits better in the second presentation, anyway).

Interestingly, I did not feel nervous about the talk until I was actually up on stage (well, metaphorical stage), but I think I managed to hide it pretty well.

After fleshing out this topic, I think I'll do a talk on fast and efficient typing (well, text editing) ;).

Recommended reading

All the links provided in the slides or presenter notes can be found in the list below:

Polymorphic method signatures

A few days ago, I was working on a new feature at work. The specifics aren't important, but it's worth mentioning that they involve object-oriented inheritance.

There was a method that all the classes shared, which takes a single argument and returns a boolean value. In the case of the base class, it was hardcoded, and therefore never used the argument. For that reason, the argument was made optional.

One class overrode this and did use the argument, though it kept it optional and opted for some confusing branches when the argument is not passed in. I was overriding this method for another class, and I absolutely required the argument.

Well, that caused some buggy behaviour, because some places in the codebase were already calling this method without an argument. I was forced to change my version of the method to accomodate a call without the required argument.

Of course, that wasn't sufficient, because the line causing the issue wanted the opposite behaviour without passing in the argument, but there were some security flaws with doing it that way (you can probably guess what we were passing in, and probably what the method does now, which I was trying to avoid, because it's not great, but eh…).

Luckily, in this case, I could just change the line causing the issue to take in the argument, but there is at least one place in the codebase that almost couldn't have happened (I could easily see a version of that part of the codebase that just did not have the argument we were looking for, and it's from a gem, so it would have been bad to change).

It probably never occurred to whoever wrote the original base method, but here are two things to take away from this:

  1. Keep your shared method arguments consistent. If an argument is optional somewhere, it should be optional somewhere else.
  2. Probably don't use optional arguments with base methods in the first place, as you never know when that argument will be required for an overriding class.