I want to create about 20,000 "Person" objects in a worker, and then pass them to the main application.
I understand that these objects will be cloned between threads and that "Person" support AMF serialization.
But I worry about performance - will my game suffer any performance hit when receiving those thousands of objects? will the current frame get stuck? or does AIR take care of it, and it will be a smooth transaction?
Will be thankful for any help on this issue.
Thanks
Update:
The objects I am creating are sort of animation instructions, not BOTs o AI.
They are downloaded in binary format, and get serialized to AS3 objects.
My game must load them during active play, and today I pay a painful price of 4-5 frames getting stuck.
If Workers would download and create them, and if the main thread would receive them without getting stuck - I would call it a victory...
I want only 1 thread, which will create about 20,000 objects.
That background thread will send those objects to the main thread.
If the main thread won't get stuck when receiving/deserializing the objects - challenge achieved.
So my hope is that the deserialization on the main thread doesn't stick it.
Am I on the right path?
Thanks for all the answers!
Related
I am receiving a stream of time-series data/events from a manufacturing process machine. I need to be able to calculate the start of a cycle and pinpoint this event based on the trough of the data. What would be a recommended way to do this?
Thanks
Edit: I've attached an image of the data graph. Basically I have an ongoing stream of data that I need to be able to effectively identify the troughs in order to establish the start of the next cycle/end of the previous cycle. The only thing I'm guaranteed not to know is the period of the cycle - it will vary.
The only thing I'm guaranteed to know is the initial datapoint value - which could be anywhere in the cycle.
At the moment - I'm kind of thinking I have to do something with a sliding span of time, keeping tracking of the minimum temp seen so far.
I'm fairly new to multiplayer design and am struggling to find the information i need to continue in my synchronous (you cannot disconnect and continue at a later time similar to hearthstone), turn-based, pvp "card" game. I'm using AS3 (flash) as my client side and node.js with javascript + mysql for the server-side processing.
In this game, the cards are created by the players themselves. It's importnat to note that these "cards" are assembled from individual building blocks (library swf files); The database keeps track of how these cards are made/assembled. Because there can be hundreds of uniqely made cards per player, i need a good way to load information about these on demand for pvp battles or for modding/deck building purposes.
What i've accomplished so far:
i have successfully sent data to server and sent data back to flash over an XMLSocket.
I have successfully assembled a single "card" from database information.
What questions i really need to answer:
Flash asynchronously loads content so i'm not sure how to approach making multiple data requests for (sometimes simultaneous) battle actions, card information, or card assembly (THere can potentially be a lot of cards and card building blocks so i feel it would be inefficient to load all data with a single request). I can either have the classes responsible make those calls OR create a messenger class to handle all requests/disconnects/reconnects/messages for the entire game.
For the global messenger class approach, I am not sure how to retrieve the fully loaded data from the messenger by upstream code (as3 continues execution even if data isnt there) or how to ensure that the request pertains to the appropriate call
i could use a ID request system to uniquely identify the socket request
i could develop a custom event driven system
I could spawn multiple messenger objects in each class that i need one. <- im leaning towards this option.
On a similar note, perhaps i should handle database requests within card objects or preload all data prior to game start (This would limit me to only query for opponent card and battle data on the fly). With the one call per card object approach I was unsure if #requests per card per player will overwhelm my server or not. Node.js scales very well but i dont have the networking knowledge to understand whether all these simultaneous request on a single port would be too much.
EDIT:
I'm strongly leaning towards using a singleton XMLSocket Wrapper or an extended class of some sort to deal with all networking transactions since that seems intuitive to me. I would highly appreciate your feedback on the best approach to notify my code that the messenger received and parsed the message it asked for (since flash will proceed with execution even if data isnt there i need a good way to do this.). I read that using custom events isnt all that terrific and there are better ways... but this is how i'd approach the problem.
For example i can do (pseudocode).
m:Messenger = new Messenger(); //this is my wrapper
m.addEventListener(new CustomEvent(CustomEvent.EVENTSTRING, parseData));
m.sendData(DataObject); //calls
function parseData(e:CustomEvent) {
xml(e.data);
}
import flash.net.XMLSocket;
import globals.*;
public class Messenger
{
public static var _Socket:XMLSocket;
public var xml:XML;
public function Messenger()
{
_Socket = new XMLSocket(vars._Server, vars._Port);
_Socket.addEventListener(Event.CONNECT, onConnect);
_Socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
}
private function onConnect(evt:Event):void {
trace("Connected");
_Socket.removeEventListener(Event.CONNECT, onConnect);
_Socket.removeEventListener(IOErrorEvent.IO_ERROR, onError);
_Socket.addEventListener(DataEvent.DATA, onDataReceived);
_Socket.addEventListener(Event.CLOSE, onSocketClose);
}
private function onDataReceived(evt:DataEvent):void {
//trigger correct event here based on data identifier w/ dispatchEvent(EVENTSTRING);
}
}
About card assembly - you should store data in database that does not require recalculation, so if a card is built out of several "building blocks", you could, for example, store a sequence of blocks in a single line of database, so that when a card info for the opponent is retrieved, you just select from player_cards where player_id=... and deck_id=... and then assemble the gathered data on AS3 side. You should definitely not put this load on server.
About asynchronous loading - make sure your PVP handshake waits for both sides to successfully process cards for both own side and enemy side. You can load data asynchronously, but you'd better do a full preload while displaying a "Loading bla-bla" screen to the player, then operate with received data. Yes, you can do multiple requests to your server, and yes, you can wait for all of them to success prior to displaying a "Battle start" screen, in the meantime AS3 will wait for the loading to complete. But, about single vs multiple request - I say go with as few as possible, because every added request at the init stage is a potential to add a thousand or so requests to a single server, and a potential to put just too much strain on your server side, resulting in a self-initiated DDoS. Make sure your database structure allows streamlining of data reading operation right into the client side, so that your server is not under a heavy load from preparing the data. But also make sure to double check whatever clients report to the server, as the primary rule of client-server games is "client always lies" assumption.
Since you are planning to make server process player actions mid-battle, you can create either temporary tables on the server (SQL-based) or state objects (process-based) that will contain current game state with links to whatever abilities the cards have and their state (in hand, discarded, in play, destroyed, etc), so that when an action from the player comes, saying "this card changes state from A to B" you can easily verify if that card is in A state, then switch it into B state, performing any actions that result from this state change on both server and client sides. Make sure to clean up this set of data once the battle is over. This requires thorough planning of your server side, so that your game engine will not stall the server while running some action sequence due to excess SQL requests, for example.
About messengers - probably you should use a session approach, together with login/password authentication this way you will have sessions available as keys to determine which battle does this data packet belongs. I think also make AS3 side periodically send pull requests to the server, which should be quickly parsed by the server and the submitted enemy/server actions returned as quickly as possible, this will also ensure that disconnects will be handled and reconnects allowed.
Overall, the question is very broad, and only tips can be given, not even examples.
I have a question about scalability. Let's say I have a multiplayer game, such as Uno, where the server handles everything. (Assume this is a text-only game for simplicity). For example, to get information printed out to the user in the client, the server might send PRINT string, or CHOOSE data (to pick a card to play), etc. In this regard, the client is "dumb" and the server handles the game logic.
A quick example of how this might work on a protocol level:
Server sends: PRINT Choose a card
Server sends: CHOOSE Red 1,Blue 1 (user shown a button or something, and picks Red 1)
Client sends: Red 1
Let's say I have this architecture:
Player Class: stores the cards the user has, maybe some methods (such as tellData(String data) which would send PRINT data, sendPM() which could private message a user)
Server Class: handles authentication, allows users to create new games, shows users a list of games they can join
Game Class: handles users playing a card, handles switching to a new player for his or her turn, calls methods on player class like tellData(), pickCard(), etc
How would I scale this, to run the server on multiple computers? Right now, all of the users connect to one server, and require the Player, Server, and Game class to interact with each other. If someone could provide some suggestions, and/or point me to some good resources/books on this, it would be greatly appreciated (no, this is not a homework assignment or something for a business, this is just a personal project and curiosity of mine). In terms of scalability, I'd like to just be able to add another server, and handle the additional load of players--but the most concurrent connections would be 1000.
Also, would this become significantly more difficult of a scalability challenge if we added in more games?
Furthermore, what is the best way to store game data? In a SQL database, or serializing objects, or what? By this, I mean let's say 3 users are in a game of Uno, and want to return to it later. I don't want to store their cards and information about the game in the Player/Server/Game class (RAM) forever - I want to dump this somewhere, so when the user logs in, the info can be loaded from however this was dumped into RAM, and then the appropriate Player/Game objects.
Finally, how can I make changes to the server without having to kill it, and restart it? Assume the server was written in Java or Python.
If anyone can provide suggestions or some resources it would be greatly appreciated - this includes changing the architecture I originally stated.
Thanks for any and all help!!
EDIT: Are there any good books or talks you all would recommend on the subject?
1.Scalability:
Involves an application architecture there across multiple server instances the session is replicated/shared and load balanced. You can choose to implement a message queue (rabbitmq) / ESB(enterprise service bus) architecture for your app.
2.Ease of scaling:
Depends on deployment and the servers you choose.
3.Pesistance:
Game for a person involves his particular game state at any point of time. If you could represent state information semantically you can have the data in markup savefiles, or store the state information directly into a DB.
Else, you may need to serialize objects and store them on filesystem / as a BLOB in DB in case the state space is humongous.
4.Hot deployment:
JVM mostly always will need a restart to reload class files, hence on java server side you will always need to restart. In Ruby/Rails is certain parts of the application can be hot deployed. If your need 100% hot deployability, perhaps Erlang is the answer.
To improve concurrency you can also use evented server/app architectures: thin/eventmachine for ruby or apache mina, jboss netty for java.
I'm thinking about system that will notify multiple consumers about events happening to a population of objects. Every subscriber should be able to subscribe to events happening to zero or more of the objects, multiple subscribers should be able to receive information about events happening to a single object.
I think that some message queuing system will be appropriate in this case but I'm not sure how to handle the fact that I'll have millions of the objects - using separate topic for every of the objects does not sound good [or is it just fine?].
Can you please suggest approach I should should take and maybe even some open source message queuing system that would be reasonable?
Few more details:
there will be thousands of subscribers [meaning not plenty of them],
subscribers will subscribe to tens or hundreds of objects each,
there will be ~5-20 million of the objects,
events themselves dont have to carry any message. just information that that object was changed is enough,
vast majority of objects will never be subscribed to,
events occur at the maximum rate of few hundreds per second,
ideally the server should run under linux, be able to integrate with the rest of the ecosystem via http long-poll [using node js? continuations under jetty?].
Thanks in advance for your feedback and sorry for somewhat vague question!
I can highly recommend RabbitMQ. I have used it in a couple of projects before and from my experience, I think it is very reliable and offers a wide range of configuraions. Basically, RabbitMQ is an open-source ( Mozilla Public License (MPL) ) message broker that implements the Advanced Message Queuing Protocol (AMQP) standard.
As documented on the RabbitMQ web-site:
RabbitMQ can potentially run on any platform that Erlang supports, from embedded systems to multi-core clusters and cloud-based servers.
... meaning that an operating system like Linux is supported.
There is a library for node.js here: https://github.com/squaremo/rabbit.js
It comes with an HTTP based API for management and monitoring of the RabbitMQ server - including a command-line tool and a browser-based user-interface as well - see: http://www.rabbitmq.com/management.html.
In the projects I have been working with, I have communicated with RabbitMQ using C# and two different wrappers, EasyNetQ and Burrow.NET. Both are excellent wrappers for RabbitMQ but I ended up being most fan of Burrow.NET as it is easier and more obvious to work with ( doesn't do a lot of magic under the hood ) and provides good flexibility to inject loggers, serializers, etc.
I have never worked with the amount of amount of objects that you are going to work with - I have worked with thousands ( not millions ). However, no matter how many objects I have been playing around with, RabbitMQ has always worked really stable and has never been the source to errors in the system.
So to sum up - RabbitMQ is simple to use and setup, supports AMQP, can be managed via HTTP and what I like the most - it's rock solid.
Break up the topics to carry specific events for e.g. "Object updated topic" "Object deleted"...So clients need to only have to subscribe to the "finite no:" of event based topics they are interested in.
Inject headers into your messages when you publish them and put intelligence into the clients to use these headers as message selectors. For eg, client knows the list of objects he is interested in - and say you identify the object by an "id" - the id can be the header, and the client will use the "id header" to determine if he is interested in the message.
Depending on whether you want, you may also want to consider ensuring guaranteed delivery to make sure that the client will receive the message even if it goes off-line and comes back later.
The options that I would recommend top of the head are ActiveMQ, RabbitMQ and Redis PUB SUB ( Havent really worked on redis pub-sub, please use your due diligance)
Finally here are some performance benchmarks for RabbitMQ and Redis
Just saw that you only have few 100 messages getting pushed out / sec, this is not a big deal for activemq, I have been using Amq on a system that processes 240 messages per second , and it just works fine. I use a thread pool of workers to asynchronously process the messages though . Look at a framework like akka if you are in the java land, if not stick with nodejs and the cool Eco system around it.
If it has to be open source i'd go for ActiveMQ, and an application server to provide the JMS functionality for topics and it has Ajax Support so you can access them from your client
So, you would use the JMS infrastructure to publish the topics for the objects, and you can create topis as you need them
Besides, by using an java application server you may be able to take advantages from clustering, load balancing and other high availability features (obviously based on the selected product)
Hope that helps!!!
Since your messages are very small might want to consider MQTT, which is designed for small devices, although it works fine on powerful devices as well. Key consideration is the low overhead - basically a 2 byte header for a small message. You probably can't use any simple or open source MQTT server, due to your volume. You probably need a heavy duty dedicated appliance like a MessageSight to handle your volume.
Some more details on your application would certainly help. Also you don't mention security at all. I assume you must have some needs in this area.
Though not sure about your work environment but here are my bits. Can you identify each object with unique ID in your system. If so, you can have a topic per each event type. for e.g. you want to track object deletion event, object updation event and so on. So you can have topic for each event type. These topics would be published with Ids of object whenever corresponding event happened to the object. This will limit the no of topics you needed.
Second part of your problem is different subscribers want to subscribe to different objects. So not all subscribers are interested in knowing events of all objects. This problem statement scoped to message selector(filtering) mechanism provided by messaging framework. So basically you need to seek on what basis a subscriber interested in particular object. Have that basis as a message filtering mechanism. It could be anything: object type, object state etc. So ultimately your system would consists of one topic for each event type with someone publishing event messages : {object-type:object-id} information. Subscribers could subscribe to any topic and with an filtering criteria.
If above solution satisfy, you can use any messaging solution: activeMQ, WMQ, RabbitMQ.
I'm pulling my hair out (once again), trying to find a way to read the activity level of audio of a NetStream, similar to how you can do it with a Microphone. I'd hate to have to let each client send it's activitylevel through SharedObjects or the like, which right seems to be the only way to actually get it to work.
Thanks so much in advance!
-Dave
In AS3 the Netstream Object has a property called .info. This holds the object NetStreamInfo. NetstreamInfo will give you all sorts of metrics. Among them is the property 'audioBytesPerSecond' which will give you an indication of the audio activity at a certain point in time. Requesting the NetStreamInfo for the incoming stream will provide you with the data from the client. Requesting the NetStreamInfo for the outgoing stream will provide you data from your own cam and mic activity. More detail on the NetStreamInfo object can be found here: http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/net/NetStreamInfo.html
NetStreamInfo.audioBytesPerSecond is unreliable.
Being a per second average, it takes one extra second before you could detect the lack of sound.
You should instead use NetStreamInfo.audioByteCount. As from Adobe documentation:
Specifies the total number of audio bytes that have arrived in the queue, regardless of how many have been played or flushed. You can use this value to calculate the incoming audio data rate, using the metric of your choice, by creating a timer and calculating the difference in values in successive timer calls.
That's probably the only way to do it. NetStream is a pretty generic object by design. The best site to ask a question like this might be on FlashComGuru.com where a lot of NetStream/FMS guys hang out.
I've seen Flex examples that displays an eq bar.
the code uses two objects
SoundTransform and flash.media.SoundChannel
it functions by dispatching a custom event that has a property which is the SoundChannel object containing the EQ of the playing audio stream.
not sure exactly how the doe works cause it's bundled up in flex, or how to get from the NetStream to the audio based SoundChannel.
The example is in chapter 15 "Building your own components" of the book "Flex 3 component solutions" by jack herrington. published by friends of ed (the pink spine books).
hope that helps.