2011-09-15

Bananananana

As I've said before, I spend a lot of time on a PennMUSH: Named M*U*S*H. It's been almost purely social for the past 12 years: A core of maybe 20-ish players that are regularly active, and up to 100 or so more that pop on and off occasionally. And I can count pretty much of all them among my friends.

There are software geeks, lawyers, students, college professors, schoolteachers,  mechanics, electricians, engineers, and more from all across the globe: Australia, Netherlands, Japan, Norway, Canada, France, Croatia, England, and more. If there was one "flaw" among the group's demographics, it's admittedly STEM (Science, Technology, Engineering and Mathematics) heavy: But those people do so frequently help each other with learning any language. You name it, somebody on the M*U*S*H has most likely done it. OcaML, Clojure, Scheme, Haskell, Erlang, all the .NET languages, and more.

Earlier this year, there was some discussion on MU* Clients: I've done a lot of work developing the server side of PennMUSH, but we speculated quite a bit on the future of the client side. One of the M*U*S*Hers, known as Talvo, maintains a TCL client named Potato. A few of us decided to give our hand at trying to make a client that might appeal to wider reaches. After the naming scheme favored by Potato, we gave named ours after other foods.

My 'entry' was Banana. Although strictly speaking, Banana is the server side, and it has several front-ends with their own name.

Banana went through multiple evolutions:

I first wrote it in Ruby, being able to fairly quickly get it going. It was good, but its threading setup seemed to be a little slow: Green threads aren't always the fastest to react when sending signals back and forth with sockets in the equation.

So I rewrote it in JavaScript, on Hairy Rhino. It worked well, and it worked fast. But it ran into problems when left running for a while: There was so much string manipulation going on in the JavaScript side, and the Rhino engine was doing it so poorly, that it started hitting OOMs despite all the checking and double checking I could enforce. Forcing GC calls worked, but slowed it _way_ down. Not acceptable. (I've since looked into how Rhino does it: It was ending up creating thousands of copies of each string during a regexp-replace!)

So, back to my home sweet home: C. Sure, I could've fixed the JS version by rewriting that little bit in Java, but where's the fun in that? Besides, it's been a long time since I got to write something in C, so C it was.

Writing it in C also forced me to refine the API to exactly what's needed: The JS (using jquery) on the client side would do the rest.

So, I did: http://client.pennmush.org/API.txt

And here's the client (You can use it to connect to M*U*S*H, or you can request an account from me on M*U*S*H to connect to _any_ mush using it.):

http://client.pennmush.org/

For icing on the cake, and thanks to the awesome folks at jquery, it runs on more platforms than any other mu* client that I know:
Nintendo 3DS (Photo credit: Chaz@M*U*S*H)

Kindle.

Anything with a relatively modern browser supporting just enough JavaScript for Jquery's AJAX features can use Banana.

Feature list:

* 'Guest' accounts: That are limited to one host:port. So mushes can create personalized "Come give us a try!" pages.
* Logging: All output from worlds are logged (not input!)
* Multiple worlds for logged-in user accounts: Connect to not just one mu*, but all the ones you frequent!
* Charset negotiation: UTF-8, latin-1, etc.
* 16 and 256 Color support
* Multiple logins: If you log into your account multiple times from different devices at the same time, they all see the same connections!
* Multiple front-ends: Once you're connected (either as a user or as a guest), you can use different front-ends: The primary: WebFugue, the fullscreening 'KindleClient', the "for development purposes only" WebCat, and two proof-of-concept front-ends: DutchMush (translates all incoming text to Dutch) and the super-wacky EngrishMush (incoming text translated to a foreign language, then back to English)

It's not yet intended for serious mudding: While there's definitely potential for them, (There's an API for saving and loading files for use with 'serious' clients!), there is, as of now, no support for triggers, macros, etc. The speed is there. The power is there (and in jquery). People can use it to make FaceBook client apps. I have somebody using it regularly on her Kindle while she rides to work. Another uses his 3DS to mush when his brother uses the computer to play games. (Isn't that backwards?)

As I'm not really interested in doing visual and client design, I'm about finished with what I want to do with Banana. For now, Banana is sitting on the backburner as a project. But if anyone wants to work on a front end, run your own back-end, or whatnot, you can get it, as usual, on GitHub: https://github.com/captdeaf/banana-muclient

(And if you're a mudder and want an account, contact me on M*U*S*H: mush.pennmush.org 4201, player Walker. Or just connect as a guest on client.pennmush.org =).

5 comments:

  1. In Ruby, did you try Fibers (in 1.9.2)? What about C extension for Ruby if there is something specific where you need the performance the most? Perhaps Eventmachine if you want async and performance?

    ReplyDelete
  2. Joshua: To be fair, I actually wrote the ruby proof of concept 3 years ago, when 1.9 was still in its infancy, then set it aside and forgot about it until the discussions surrounding clients earlier this year. In addition, it suffered from a few of the same issues that the Rhino JS version did when it came to converting massive amounts of text, line by line, from ANSI color codes and iso_8859-1 into HTML and UTF-8. But most damning: I didn't really sit down and do any program design until I was somewhat into the JVM version.

    But most simply: I switched away from Ruby because I felt like it. Ruby's still among my favorite languages, and I think it's very, very, very well designed, but its implementations need to catch up to the others in order to be production ready.

    ReplyDelete
  3. Hah, cool.

    ps: what implementations need to catch up?

    ReplyDelete
  4. Joshua: Ruby 1.8 series performed abysmally. 1.8 is, sadly, still the default ruby for many installations. My OS X Lion comes with Ruby 1.8.7.

    1.9 is _much_ better performing than 1.8, but it still lacks actual concurrency: a global interpreter lock. Certainly, there are benefits to "green threads" and clustering is becoming more popular than threading, but there are instances where separate threads are needed. YARV also doesn't have JIT compiling, which would give it more of an edge.

    JRuby, last I checked, only had 1.8.4 implemented, no support for features added in 1.9. But on the flip side, it is JVM-fast, and has true concurrency.

    MacRuby, again last I checked, was at something like "80% of Ruby 1.8 feature list implemented."

    But, with the advances in 1.9 and JRuby, I suppose it's no longer fair to say that it isn't production ready. But running rails sites on 1.8 is still a disaster.

    ReplyDelete