Monday, May 30, 2011
Report and presentation
We are nearly done with our bachelor's thesis, yeeha!
You can download out thesis from here:
A Generic Game Server - Bachelor's Thesis (PDF)
And today we gave a 20 minutes presentation, here are the presentation slides.
Sunday, May 1, 2011
JavaScript Virtual Machine in GGS
Oh yeah, thanks to Mattias work this week we are able to use JavaScript as a programming language for our games now. There remains still a little bit of work but it does not hang when we try to get something into of from the database, check this out:
2> GameVm = ggs_gamevm:start_link("test_table"). <0.85.0> 2> ggs_gamevm:call_js(GameVm, "GGS.jeena.setItem('a','foo')"). undefined 3> ggs_gamevm:call_js(GameVm, "GGS.jeena.getItem('a')"). "foo"
This is so awesome, I won't be able to sleep tonight :D I think I need beer or something :D
What needs to be done now is to adapt the code so the first client, who will act as kind of a host, is able to upload the server source code (JavaScript) at the beginning and then other clients shall be able to connect to this one table.
Tuesday, April 26, 2011
Second testing session
When the GGS was operational we started to connect bots, the messages per second reached 5000 when about 200 bots where connected. However the number of messages per second did soon decrease to about 3500 even though we added more bots. We continued the testing for a while and the server did never proceed more than 5000 messages per second, most of the time it was pending between 3000 and 4000 messages per second. The conclusion we can draw from this is that the GGS currently is limited to around 5000 messages per second and when this number is exceeded the server will queue messages. A short message queue is acceptable but when it becomes to long the clients will get delays and the game will be impossible to play if to many clients are added to the same server.
The blue line is the amount of clients, the yellow one is how many messages per second the clients send and the red one how many messages per second the server ist sending to the clients.
Thursday, April 14, 2011
Stress testing
Here are the conclusions we reached today, the stuff we need to work on, and
the thoughts that came up when we tested the application.
*Can ping be used to measure the network saturation?*
Quite possibly yes; ping measures the round-trip time of one ICMP packet (as
far as I know), and "if all goes well", the RTT will be the same for all
packages. It is possible, though, that some harwdare (read: the switch)
prioritizes ICMP packages through QoS (I think it's called that). It's also
possible that the OS treats pings differently than other traffic. This is
the main "problem" I have with using ping to measure saturation. We should
look these things up, if pings are not specially treated, they are a good
measurement of saturation.
*Optimize network traffic by sending less data*
This is obvious. Less traffic means less saturation. We should/could/may
send less data, and therefore increase performance both by removing the
(potential) network bottleneck, and remove some processing load from the
network cards / network stacks of the OS:es.
*Are screen print-outs a performance issue?*
We can possibly lower the IO bottleneck by removing printouts, we did this.
There is a information loss here for us when debugging, so a tradeoff has to
be made. A logging system which is customizable would be ideal.
*Load average*
On Niklas' machine the load was *really* low, on my machine it never went
below 1, and never above 1.3. On Richard's Mac it was like 4.. Is this
really a good measurement? Are there others which we can use? Erlang has a
notion of "reductions" - maybe we can use that? Maybe we can measure the
processor time consumed?
*# sockets limit*
Common machines seem to have limits on open files, and this includes
sockets. We should look at how web servers are configured here. Is it common
to raise this limit.. Are there penalties / alternatives to this? On Linux,
change /etc/security/security.conf to increase the limit.
*Warning; Mnesia is overloaded!*
Can we use the DB less? Exactly what does this mean? Can we use a different
machine as DB server?
*Can we get super-accurate CPU stats?*
Can we get stats from /proc/ instead of top and the likes? Can we compare
different CPUs easily? Remember that the important thing is how the system *
scales*. How much more load do we have when there are 20 players compared to
10, for example.
These are the notes I kept when we did the tests. I think we can discuss
these topics in the practice section of the report, once we've figured them
all out!
Wednesday, April 13, 2011
First attempt to get some statistics
We had a look at the load of the computer which run the server and it was not really stressed but only up at a load of ca. 0.31. The problem seemed to be the network we have been working on, it was a ad-hock WLAN network between all our laptops which isn't the fastest. And since we use TCP which resends all the data packages which got lost we got quite a big amount of traffic and therefore a high round trip time ("lag" in game speek).
For the future we want to try to get a GB-network-switch and attach our computers via cable. It's a pitty that we will not have the time to implement UDP to get it working with lower lag.
Another bottleneck was running all the bots, which are written in ruby (and each bot is a real process), on our limited amount of laptops (we had only 3). Jonatan was able to start ca. 2500 on his linux machine but I, on OS X, was only able to start ca. 200, after that it said I was not allowed to start more processes. Therefore, before we will be able to do some real statistic stuff, we will implement the bots in erlang, processes there are cheap.
But it was a great feeling to see 1500 games of pong, it is indeed a real time game, running on our GGS-prototype without having performance problems other then the network-bottleneck.
Bots playing Pong
We have to do some more work before we can run thousends of games simultanously, but I think it will work next week or something. Then we will produce some nice statistics for our report.
You can take a look at the code, it is implemented in ruby and I devided it into different "modules" so we can reuse the GGSNetwork in other games too: https://github.com/jeena/GGS/tree/master/games/Pong-bots
Writing the report is working quite well too, we already have 15 of the minimum 30 pages with actual relevant content. We'll have to work on the language though.
Thursday, March 24, 2011
Some rewrites, report, status
Perhaps the more important thing is that we changed the direction of our thesis from "just" implementing a game server to researching about scalability and fault tolerance of game servers at a academic level. Currently we are reading many scientific reports and books about scalability and fault tolerance and try to be as scientific as possible when we write our report. You can actually take a look at it: https://github.com/jeena/GGS-report
We still want a working Generic Game Server but it won't be a real world product but more some type of a prototype of such one where we test our hypothesis on performance, fault tolerance and scalability if we need to get our hands dirty.
To be able to test such stuff we need to write some bots which will play games via our server. And we need to write code which collects data during the games.
To get the code more stable we are trying to replace our unit tests with quickCheck tests.
Hope the project is still interesting for you who have been following it until now :-)
Monday, March 7, 2011
Texts and presentations
It was a little bit quiet here on the blog for the last two weeks, but this doesn't mean that we had vacation or something. We have actually been writing a lot and I'd like just to load up the stuff here so you can read it if you want. This are links to PDF:s
Monday, February 28, 2011
More fault tolerance & protocol improvements
The problem seems to have to do with the way sockets are implemented in Erlang, and I'm sure there is a way around this, we just need to find it. Other than looking at the dispatcher, I also changed all outgoing communication to also use our protocol, previously it did not. I wrote a very rudimentary protocol "message builder" for this purpose, and also a very very simple parser for python.
The chat client now uses the protocol both for receiving messages and also for sending them. As a step in the direction of game loops not written in Erlang, I redid the "identification system" for player and table processes. Previously we handled all communication using process IDs, which is really handy when doing game loops in Erlang, since you get a unique identifier, and at the same time a way to communicate with the process. When moving outside Erlang and into JavaScript for example, this is not as convenient.
I wrote a post about why we need UUIDs for describing players, and this is what I have implemented, both for tables and for players. Now all identification of tables and processes are in the form of UUIDs and not process IDs.
Friday, February 25, 2011
Fault tolerance & chat
This is interesting because this is the first usage of ggs_db, and I can conclude that it works nicely.
I have also added some fault tolerance to the ggs_coordinator. Now clients are unaffected by crashes in ggs_coordinator. This was mostly accomplished by adding a backup server which ggs_coordinator can restore it's old state from when it crashes, but also by changing the startup routine of new tables.
Previously we created new tables using gen_server:start_link, but this didn't work very well. ggs_coordinator becomes the parent process of all tables, and when ggs_coordinator goes down, it brought all the tables down with it. I solved this by using gen:server:start instead, and also I enable trap_exit to catch any exit messages.
Many features of GGS have now been tested using GGSChat, and next in line is the room creation feature. Currently all clients join the same room when GGSChat starts, I want to be able to specify a room. This makes the chat a bit more IRC-like.
Oh, here's how the chat looks now:
Wednesday, February 23, 2011
Brain storming
One thing that we had discusses, but never really formalized was the idea of a rule enforcer, who checks if a rule is broken when a move is made, or rather, if a move is legal or not. Our supervisor had previously asked us if it would be possible to change the rules of the game while it was commencing, and this is a great way to do this, we think. The enforcer will have a list of all the rules, and checks each move against the rules, if a rule is broken, the enforcer will stop the player from performing the bad action. A bit like a policeman, or a judge in soccer.
Monday, February 21, 2011
Bulk update
Board game classifications
Strategic play: Choice is based on multiple turns. Example: Openings in chess. Tactical play: Choice is based on current turn only. Example: Having the knight perform check while simultaneously threatening the queen.
informal games: Undirected play. As in a playground.
formal games: Games with means and ends.
where
Means consists of are predetermined set of rules and equipment.
Ends are a set goals to accomplish through contest.
Game board:
* A flat surface. Example: Chess
* Tile laying. Tokens stacked on top of each other.Example: Scrabble(Afapet in swedish)
* Boardless. Boards which isn't flat like 3D boards or no board at all. Example: Yatzy
Combinatorial games
Discrete: No simultaneous moves
Deterministic: No luck
Perfect information: No hidden information
Finite: Well defined outcome after first nr of moves
Race games: Players trying to be the first to reach from start to end. Example: Parcheesi
Space games: Arrange pieces into patterns. Developing and disrupting the enemy. Example: Three in a row
Chase games: Hunter and pray. Capturing and entrapping. Example: Cops & robbers.
Displace games: Capture a fixed nr of opponents pieces. Example: Fox games.
Fixed: Nr in a row, Target pattern. Example: 3 in a row
Variable: Pathmaking. Territorial. Reach a goal. China chess.
Sunday, February 20, 2011
Board game decomposition
Source of inspation: Decoupling Aspects in Board Games Modeling
This is the core of the game.
Agents:
Users of the game. May be humans or computers.
How the game is presented to the user. Possibly with figures cards and tokens. Usually expresses the game logic, making it reasonable for the user.
States:
The conditions of the game at each turn.
Behaviors:
Transitions from state to state.
Rules:
Static laws producing the behaviors in the game.
Administrive agents:
Upholder of the rules of a game. Like the bank in monopoly.
Players:
Players playing the game.
Saturday, February 19, 2011
Game Semantics
Example: An expression written using a newly defined model compared to a lambda expression.
The reason is to have the simplest most well fitting syntax for the domain being studied. In this way it will be easy to understand expressions even as they become complex.
How could GGS benefit of game semantics? There probably exists optimal models to express all sorts of game behaviours. I believe you could have an application reading the history of gamestates and parses them with respect to such a model and then represent them to a user. These sorts of applications is not our main concern but could probably very easy be used in conjunction with GGS. Or maybe even built into the javascript game.
Another idea would be able to send such expressions to the game in runtime. Therefore enabling players to modify the rules of the game. Unfortunately GGS isn't powerful enough being able to support that idea. * You would need to translate whatever the game expressions are into java script. * The ability to reload the gamefunctions inside spidermonkey in runtime. * Alternatively having multiple virtual machines running simultaneously, cross communicating. This would be even harder as we would need to write our own vm and having them communicate with each other.To summarize: Adding this kind of support to GGS would direct the focus from our current goals of not having to implement network support by oneself, to creating a game design tool with networking and communication support.
Friday, February 18, 2011
Semantics
I found some links about game semantics, game design languages and structures in board games which I've been looking into. The purpose is to get in touch with these subjects so that we will be able to find out what of this should be supported with GGS, what we will implement or what would easily be implemented by others. If not then give reasons and use the material while writing standards. Together with this I wrote a brief summary of the word Semantics for everyone to enjoy.
Semantics. The study of meaning according to wikipedia.
It is learning about the meaning of different words and symbols and how they together build up sentences which then has new meanings.
Applied to computer languages,this is learning about how they work and compare their syntaxes. Make abstractions of them and create mathematical models.
Wednesday, February 16, 2011
A bit of a rewrite
Today we realized that our old structure of GGS wasn't very good, so we decided to redo it! We have learned a lot developing the "old" structure of GGS, such as how to use supervisor structures properly and which the big parts of the application are.
Anyway.. Using this knowledge, we sat down and really thought through which interfaces we need internally. We also asked ourselves "what happens when this part of the application fails?", and provided solutions for this. In the end, I think we came up with a pretty nice solution.
We now represent all clients as separate processes, and we have a coordinator process which connects different clients with different games. The idea is that this coordinator process should be able to rebuild the entire server in a different location, and thereby easily provide replication.
We all sat down and created stubs for the new design and documented the design in this document, and I later sat down and implemented the basic supervisor structure and socket communication, just so we have something runnable.
I predict we will soon be up and running with the same amount of functionality we had with the previous design, much of the code was written in such a way that we can simply pop it in to the new design.
Time report:
Today: 8 hours
Yesterday: 5 hours
Tuesday, February 15, 2011
Joe Armstrong on Erlang lecture
Today we all have been on a lecture held by John Armstrong - who is one of the inventors of Erlang - on Erlang. The lecture seemed to have been made exactly for us with our problems.
Is Erlang the answer?
In that case what was the question?Joe Armstrong
Programming languages are used to solve problems.
But what problems? Erlang solves a few interesting problems.
What problem does it solve, and why are these problems interesting?What big problems are left in computer science and how might we solve them?
What's gone wrong with computer architectures and what can we do about it?
This talks looks back at the history of Erlang and forward to a future where one day software might actually work and be useful. Right now software is in a bit of mess, but there are ways to fix it ...
I'll tell you more next Tuesday, ...
/Joe
At first he talked a little bit about the history of Erlang, which was interesting but most of the stuff you already knew from books and so on.
Message passing and processes
He wrote a interesting paper about OOP a while ago: Why OO Sucks
One of his tutors said, after reading this "Why OO Sucks" paper, You got it all wrong. You know, Erlang is probably the only really object oriented language because the main thing is not at all the classes and inheritance and stuff, but message passing and code encapsulation
. (I paraphrased here, can't remember the exact words he used).
Just yesterday I tried to explain to the other guys why we really should use asynchronous message passing instead of synchronous, I never could wrap what I was thinking and feeling about it into words. But lucky me, Joe did exactly that today for me, so I think we now agree on that we want asynchronous message passing for our server.
Another anecdote was that he once gave a talk in Germany about Erlang and some server programmer said that their server would serve data for about 10000 users he wouldn't need Erlang to acomplish that. Joe asked him: If something goes wrong in your server and it crashes, how many users does this affect, all the 10000? Our server only serves one user, but we start 10000 server processes to serve data to every user, when it crashes it only affects that one user
. I must admit, it got me thinking.
Protocols
He also talked about protocols and that he never liked the fact that there are sooo many of them, he counted about 4900 or something like that. We felt like he was talking directly to us, because during the last two weeks we have been doing exactly that, designing a new protocol :-/.
In 2002 he proposed UBF, but as he states in his blog in february 2009, This scheme was never widely adopted - perhaps it was just to strange...
. During the whole lecture he never mentioned a real world alternative to designing a own protocol, so during the Q&A session I asked him directly what we should use today instead of the protocol designed by ourselves.
He had to think about this question for some time and said That is a good question
:D, but then he mentioned Google Protocol Buffers and Facebooks Thift. He said we should have a look at both and then just pick one, and we should really do that.
Realizing that this would be the right thing to do crossed my heart a little bit because I was a little bit proud that we had developed a simple to understand but flexible and powerful protocol.
So tomorrow we will have a closer look at Protocol Buffers and Thift and try to decide if one of them suits us good enough. I assume that we will rethink our structure and if we should use more processes or something. After all it was the perfect lecture in the perfect time for us.
Monday, February 14, 2011
Internal interfaces
Today we found out that there is no way to continue programming together without first defining some internal interfaces for our erlang modules. Every time someone added some functionality it broke the entire application because of the changed method calls.
So we decided to set up a new Wiki page: Interfaces
Untill now there are only three interfaces, the ones we are working on right now, but we want to add a interface for each of the modules we use. They will help us to structure the application and to easy understand what each module is supposed to do.
We tried to do that by the "Single responsibility principle", where each module only has one responsibility. If its doing more than one thing then obviously it needs refactoring.
Time: 10 hours
Improved protocol & test app
Today we had a meeting where we discussed the structure of the new protocol module. We ended up with a resursive solution which looks much better than the old one. This new module allows us to write more powerful handlers in ggs_server, so that's very good.
I've also written a little GTK application to demonstrate GGS, just a simple calculator. The important features of the calculator is the calculate button, and the connect button, which interact with GGS.
Time report
Approx. 8 hours today
Thursday, February 10, 2011
Usage of javascript
JavaScript has gained a lot of popularity lately, it is used in large projects such as Riak[1], CouchDB[2], PhoneGap[3]. On the popular social coding site GitHub.com, 18% of all code is written in JavaScript.
When starting a new project, it is nice to have a low learning curve, to attract new users. Using a language that many people already know about means you get a lot of potetial users right away.
The popularity of JavaScript in the programming community, in combination with the availability of several[4] different JavaScript virtual machines was an important influence in choosing JavaScript as the main control language for GGS.
In addition to JavaScript being a popular language, both CouchDB and Riak mentioned above use Erlang.
References:
1. http://wiki.basho.com/An-Introduction-to-Riak.html
2. http://couchdb.apache.org/
3. http://www.phonegap.com/about
4. http://www.mozilla.org/js/spidermonkey/, https://wiki.mozilla.org/JaegerMonkey, http://code.google.com/p/v8/
Tuesday, February 8, 2011
Literature Quest
I also read a report which was mainly focused on postmortem analysis of crashed Erlang applications / systems, and included a new tool to aid in this. This tool was cool and all, but what was really good about that report was that it also covered a good deal of how to properly write fault tolerant Erlang applications.
In total I spent around 6 hours
Sunday, February 6, 2011
Exposing C-functions to Spidermonkey
Today I implemented my very first additional function into Spidermonkey, it was just a test function which just responds with a static string but anyhow, this is hot shit! We will use it to call Erlang functions from JavaScript to implement something like webstorage. here is some code, the js_erlang() function which will be exposed to JavaScript:
JSBool js_erlang(JSContext *cx, uintN argc, jsval *vp) {
const char *s = "text comes from C function";
JSString *str = JS_NewStringCopyN(cx, s, sizeof(s));
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(str));
return JSVAL_TRUE;
}
And here is how you add it to all the other native functions in Spidermonkey:
JSNative *js_erlptr = (JSNative *) *js_erlang;
JS_DefineFunction(vm->context, JS_GetGlobalObject(vm->context), "callErlang", js_erlptr, 0, JSFUN_FAST_NATIVE);
Because we wanted to add this, we had to fork the erlang_js project, I hope we can write code which is general enough so it will be back ported to the original project. Here is our version.
The next step is to get the argument from the function, I suppose it'll look something like that:
jsval *argv = JS_ARGV(cx, vp);
jsval js_arg = argv[0];
char *argument = JS_GetStringBytes(JS_ValueToString(cx, js_arg));
And after that we have to call a erlang function. Jonathan found this neat erlang helper called erl_call. With its help you can call functions in a node:
me@Zepto$ echo "[2+2, node(), \"Hello world\"]." | erl_call -sname ggs -e
{ok, [4, ggs@Zepto, "Hello world"]}
And you get an answer from the erlang node in plaintext. This looks like the easiest way to talk to erlang yet. You probably saw the argument "-sname ggs" and wandered what that is. It is the name of the node you would like to talk to, here "ggs".
Time report
Today: 7 hours
Saturday, February 5, 2011
Fault tolerant GGS
The {ReferenceID, JSVM} tuple stored in the ggs_server state was previously lost when the ggs_server crashes, but this is now stored in ggs_backup as well, and this is where the fault tolerance takes place.
ggs_server may now crash at pretty much any time, and resume its state from ggs_backup. This works according to the following:
- ggs_sup starts
- mnesia_ctrl starts
- ggs_server_sup starts
- ggs_backup starts
- ggs_server starts
If ggs_backup is to crash, the ggs_server_sup will restart it, just as it restarts ggs_server, and the state is reloaded from ggs_server, unless both ggs_server and ggs_backup crash at the exact same time.
For some reason though, the JSVMs stored in the ggs_server state do not live through the migration to ggs_backup and back, most likely due to them being spawned from inside ggs_server and not being supervised properly. This problem should be easily solved by supervising erlang_js on a higher level.
UPDATE: Moving erlang_js to a higher hierachy is not the solution to the JSVM death issue. The JSVMs disappearing when ggs_server crashes is a design choice coming down to the new/3 function in js_driver.erl in erlang_js.
new/3 creates a connection to the erlang_js driver using an open_port command, and this command registers the calling process (ggs_server) as its port owner. Looking at the documentation for ports we can see that when the port owner dies, the port is supposed to go down as well. I see two possible solutions to this:
- Change the owner of the port to ggs_backup when ggs_server crashes, and then back again
- Set the owner of the port to a process which should not ever go down (thanks)
Update 2: A different approach is to incorporate the "wrapper" inside erlang_js so we don't need to see it, we just do our js:call/? calls and those are handed of to a "persistent" process inside erlang_js which registers its JSVMs to that process.
Time report
Today: 5 hours
Updating day: 1 hour
Friday, February 4, 2011
Protocol changes
We still have not implemented unique IDs for the users, so if more than one user connected at once, there'd be a 0.1% chance that they get the same ID!
The javascript running code is really simple at the moment, and Jeena is working on improving it.
The supervisor tree graphic that was shown in the last post is now implemented. We have an mnesia controller which we can use to communicate with mnesia, we still only have one ggs_server though.
I and Niklas also went to the library to learn more about their databases, it was very informative and will certainly prove to be a great resource.
Time report
Yesterday: 3 hours (including meeting w/ supervisor)
Today: 4 hours, working on the protocol, 2 hours in library = 6 hours total
Tuesday, February 1, 2011
Supervisor
Now the supervisor is active and working in our little GGS. Currently there is one root supervisor, which supervises the ggs_server process. Once the ggs_server process dies (which can be forced by a __crash command), the supervisor restarts it.
The problem is that the ggs_server process holds valuable state, which we need to propagate to other ggs_server processes for reliability. The next step is figuring out how we can run two (or more) completely mirrored ggs_server processes, and bringing one down doesn't wring the other down.
The network part of the ggs_server module should also be moved out to ggs_network, similar to how the application level protocol is placed in ggs_protocol. The actions taken by ggs_server when a message is received are currently not implemented in an "OTP fashion" and should be rewritten as such (should be simple).
Yesterday, we spent some time discussing and implementing the protocol which we use to communicate to the clients and back to the server again. This ended up as the ggs_protocol module. Also, yesterday night (this morning..) I implemented {client, JS-VM} mappings in an OTP fashion in ggs_server.
The picture below shows the supervisor setup we are currently working towards. The tree depicts the GGS system running on one machine, when run on several machines, we need to link several of these trees together
Time report Yesterday (day): 4 hours Yesterday (night): 2 hours Today: 3 HoursRandomness and Identifiers
- The refs are not really intended to be sent over network in binary form (or so it seems at least)
- When converted to binary, they are quite large
- According to [1], they are unique to "approximately 2^82 calls" - which is a bit vague.
- It is designed to be used over a network [2]
- It is designed to be used for objects with a long life [2]
- http://www.erlang.org/doc/man/erlang.html#make_ref-0
- http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
- Section 3.0
Sunday, January 30, 2011
GGS simulator in JS
First I wanted to code a counterpart to Mathias Python-Tic Tac Toe in JavaScript, so we could test our Server and work with two different platforms for the game, but then I ended up writing a GGS-simular in JavaScript.
Doing so I found many WTF?:s for example having just a array with users and no getUserForId() method is retarded, every time you do something you need to iterate thru all users to find the right one.
I tried to work with the world object, the localStorage object and the users array, in order to not pollute the space I bundled them all in one GGS object.
One very odd thing came up, if you're used to programming object oriented, you use many instance variables and save there objects, etc. You can't do that if you want your game to go on after your spidermonkey instance crashed. I'm not sure how people will react to such a shortcomming.
Here is how a game on our Generic Game Server could look like: TicTacToe.js.
You can take a look at the server-simulator too, It doesn't work in IE GGS simulator
There are two instances of the game in different windows (frames), the do not talk to each other directly but via the GGS API and the simulator. In the future I want to add some stuff like random game-crashes and random latency.
Time report
Today: 14 hours
Friday, January 28, 2011
Webstorage
Today me and Mathias spend the whole day trying to figure out how to fix the problems with the JavaScript API I talked about the other day. node-overwrite doesn't work for us, because it doesn't have to do much with the way we do things and only works for node.js
world
-object
The main problem we had was that we wanted someway to map a erlang dictionary to a JavaScript object but couldn't figure out how to expose a host object to the JS-VM. Then Mathias said that it can't be possible to do it in a easy way because there are no variables in erlang, erlang is a functional language and you alway just get copies. Put it that way, even I got it why no one has done that before.
So we had to do it the erlang way, get a copy of the data, modify it and send a new copy back to erlang. I recalled a W3C specification called HTML5 Webstorage which tries to deal with exactly the same problem, to let the JS-Programmer to store data locally. This is their interface:
interface Storage {
readonly attribute unsigned long length;
getter DOMString key(in unsigned long index);
getter any getItem(in DOMString key);
setter creator void setItem(in DOMString key, in any value);
deleter void removeItem(in DOMString key);
void clear();
};
As you can see, it is not possible to store hierarchal data like Arrays or Hashes. So if you't like to do that, you'd have to serialize and deserialize the Array/Hash. At first we thought that this was a very dumb idea because it would take way too much time to do that. But then we had a look at the erlang_js implementation, because we wanted to know how they communicate between erlang and the JS-VM. Astonishingly they just use plain JavaScript stings via a socket to talk to a C-application which holds a instance of Spidermonkey and which just executes the string in Spidermonkey and if there is a return, returns this as a string back to erlang via this open socket connection.
Ok, now there was really no need to try to make it more complicated as it had to be and we decided that if you would like to store structured data like arrays or hashes in our key-value-localStore you'd have to use JSON.stringify()
and JSON.parse()
.
That way we can offer a really easy to use API which people know from the JavaScript-Web-world. There is a good specification of that, example code en mass and there are many people you can ask. And we like the idea of using as many already available standards as possible.
Public and Private data
Obviously every time you use the setter or deleter method we will notify all clients about that. But what if you just want to save something which should not be distributed to all clients like some counter or other private data which no client should know about? Then we will, like the W3C proposes, offer a localStorage
object which too saves the data persistently, but does not distribute it to all clients.
Last but not least there will be a Users array with all of the users who are logged in into this game. Every user-object will have at least an id, a nickname, and methods to talk to just to his client.
Time report
13 hours
Gomoku
Tic-Tac-Toe
Thursday, January 27, 2011
Trying out Google V8
Time Report
Jan 26, we had a meeting between 13-15, so 2 hours
I worked with V8 between 00.30-02.00, so 1.5 hours
In total: 3.5 hours.
Wednesday, January 26, 2011
Problems with key-value store via JavaScript API
Problems with key-value store via JavaScript API
For security, concurrency and high scalability reasons we wanted to expose a key-value store, which would be implemented by us in Erlang and use Mnesia, as a convenient API for the game programmers in JavaScript.
I wanted for example have a "world" object, like for example the "document" object in browsers. You should be able to use this object like every vanilla JavaScript object, except that it would not store functions, only primitive objects {}, arrays [], strings "foo" and numbers 1.63.
You would set and get objects like this:
world.foo = "abc";
console.log(world.foo) // returns "abc"
world.bar = { "myArray": [99,33,1] };
console.log(world.bar.myArray[1]) // returns 33
and so on. Every time you save something in this object, we would need to call a setter method which would call a erlang function which would save the data in our erlang-database. The problem is, that this seems not possible and easy as I thought in todays JS-VMs.
At first I thought about getters and setters in JavaScript, but if you have a look at the code, then you see that you already have to know the name of your properties.
What we would like to have are something like "default getters and setters" which would be called even if the property isn't there yet. There is the non standard __noSuchMethod__(id, args) in Mozillas spidermonkey, but it only is called on methods world.undefinedFun()
, not on properties like world.undefinedProperty123 = "test"
.
I talked to the guys in the irc://irc.epd-me.org/#selfhtml, they often know a lot about JavaScript, and got a link to something very promissing, but sadly not implemented yet, harmony proxies (bugtracker) in Googles V8 JavaScript engine. In the bugtracker comments you find a link to node-overload which is node.js addon that provides an Watchable class that has getters/setters without property names
. And node.js is a server running in V8. I don't know if we'll be able to use it, first need to have a deeper look at it, but it looks like it would do what we want.
Time report
16 hours
Hello Mnesia!
Preliminary thoughts about the planning report!
In todays meeting we talked about how we should design the planning report and which things to focus on when we write it.
The main motivation behind the project are to facilitate the development of network based games. In order to achieve this we need high scalability and high reliability(one reason to use Erlang). We also want to see how Javascript(JS) works in combination with Erlang, will it be extensive enough and provide the required stability? Another thing that we need to investigate are the connection JS->Erlang, this is currently not supported by erlang_js and before we choose what to use we will need to look at other alternatives.
With the project we want to deepen our understanding of Erlang, JS and how we can make links between different programming languages. We aim to build a reliable server that will make use of the possibilites that Erlang together with OTP gives us. It will also be interesting to see if it is possible to run a distributet game server in reality?
We want to give game developers the possbility to develop small multiplayer games easy and quick without the need to have knowledge about networks and network programming. The project will have a clear link to web applications/web games. We will strive to make it as easy as possible for the game developers, we hope to create an API that is easy to use.
Tuesday, January 25, 2011
Meeting with tutor, and first code session
Time Report
We spent today, from 11 - 16.30 (5.5h) working on this.
Friday, January 21, 2011
About erlang callbacks from within SpiderMonkey
Using erlang_js
- Make sure the sasl application is running.
- Start erlang_js.
- Create a Javascript VM via js_driver:new/0.
- Use the js module to execute Javascript.
Fourth meeting
Thursday, January 20, 2011
Which interfaces and API:s do we need? (meeting 3)
Time report
9 hours
Wednesday, January 19, 2011
We need an API
Time report
8 hours
Our second meeting
- JSON
- Binary PLIST
- BSON
- It is easy to construct
- easy to read
- readily parsable in javascript
- There will be a lot of overhead
Tuesday, January 18, 2011
First meeting
Time report
8 hours