I have been working on a PhoneGap plugin to enable WebGL, intended for publishing HTML5 games to mobile. It's called WebGLGap. However, PhoneGap's way of calling plugin code (via exec) typically involves stringifying all the parameters to JSON, then parsing it on the other side again. According to this question, this has not changed even in PhoneGap 2.2 which was advertised as having a faster bridge. For something like WebGL, this is absolutely untenable and kills performance (<10 FPS) even for simple demos. This is because in many cases, especially 2D games, every frame must transmit a large block of JSON data representing all the WebGL commands to run. This includes all vertex data - imagine a huge string of "0.959455, 0.959595, 0.588575, 0.585858..." etc every frame.
Obviously stringifying and parsing is an unnecessary and inefficient step, but I'm struggling to find a way to pass the JSON data from JS to native which avoids that. Ideally this should work on both Android and iOS, but I'm happy to stick to an Android-only solution for now. Does anyone have any ideas about the most efficient way to do this?
Linkedin use Web Sockets for their iPad app. Might be worth looking into: http://engineering.linkedin.com/mobile/linkedin-ipad-nativeweb-messaging-bridge-and-websockets
Some of the benefits that you're looking for
WebSockets can communicate asynchronously from JavaScript to native.
WebSockets don't have a payload limit
WebSockets don't require us to encode our JSON strings as URL parameters
WebSockets should be faster than URL scheme navigation
Addressing performance
Looking at CordovaPlugin.java, as you mentioned, everything is a String:
public boolean execute(String action, String rawArgs, CallbackContext callbackContext) throws JSONException {
JSONArray args = new JSONArray(rawArgs);
return execute(action, args, callbackContext);
}
If, for example, the conversion from String to JSONArray is the only bottleneck, then you could override this method in your plugin and perform your own deserialization. It's a small performance improvement, but it might be worth investigating.
Creating an alternate bridge
As for creating an alternative bridge, that's trickier. I don't know much about Cordova / PhoneGap, but from what research I've gathered, Cordova exposes a specific Javascript interface via addJavascriptInterface. If you could implement your own NativetoJSMessageQueue, you might be able to wire it all together.
EDIT
After conducting a bit more research, I can provide a bit more direction. The really relevant part of the NativetoJSMessageQueue is the various BridgeModes it implements (see line 92). You could look at the other bridge modes as an example.
Unfortunately, the NativetoJSMessageQueue has exactly four bridge modes registered; assuming that you could implement your own bridge mode, you would still need to some how register it as a new mode for the NativetoJSMessageQueue.
I'm not sure what exactly you want to do but I notice that in your project you are converting the JSON to String and then you will pass it through the PhoneGap plugin , convert it to JSON and then convert it to Matrix!
what if you keep your data in a string and convert the string straight to Matrix?
this way you can skip the converting to and from JSON part
On android, you can try to use the addJavascriptInterface (link to WebView's documentation) method of the WebView to "inject Java objects into the WebView", which is the approach PhoneGap uses to add the apis for geolocation, filesystem, etc.
I guess this will be faster than using the plugin approach (didn't test this yet).
Check the code of the PhoneGapView, which extends WebView:
https://github.com/phonegap/phonegap/blob/3c7324ea8b3944b6e5d3d91e9e328c9c3939464b/android/framework/src/com/phonegap/PhoneGapView.java#L42
UPDATE
After all, this only works for simple types such as int or String, like you said in a comment below.
Passing a JavaScript object using addJavascriptInterface() on Android
Trying to do otherwise will result in exceptions from within the android.webkit.WebViewCore and android.webkit.JWebCoreJavaBridge classes.
UPDATE 2
Well, the best code you'll achieve using this approach will be something like this
(from https://github.com/commonsguy/cw-advandroid/blob/master/WebView/GeoWeb1/src/com/commonsware/android/geoweb/GeoWebOne.java#L80):
public String getLocation() throws JSONException {
Location loc=myLocationManager.getLastKnownLocation(PROVIDER);
if (loc==null) {
return(null);
}
JSONObject json=new JSONObject();
json.put("lat", loc.getLatitude());
json.put("lon", loc.getLongitude());
return(json.toString());
}
and most likely, all parameters should be string'fied (or JSON'fied...)
This might help you if you have a performance hit when triying to create strings from javascript side: http://www.javascripture.com/ArrayBuffer
I've read about encoding data in png. Here is the original article: http://cg.alexandra.dk/2012/11/26/webgl-tutorial-optimizing-data-transfer-for-webgl-applications/
Might be useful.
Given that json is very inefficient, you may gain a lot of performance if you take this route:
server side:
data model -> protobuf (build() to binary) -> encode base64 (binary to string) -> add as one json field or payload (best is to pass binary blob as a payload, but I'm not sure if PhoneGap allow this)
client side:
decode from base64 (string to binary) -> protobuf (parse from binary) -> use the protobuf objects directly as deep as you can in your code - it's extremely efficient data model
Related
I'm developing a web application with Go on the server, and the router will use PushState, so the server will also have to be able to render my templates. That means that I'll need a templating engine that works with Go and Javascript. The only one I've come across so far is Mustache, but it doesn't seem to be able to handle lowercase properties of structs, and there also doesn't seem to be a possibility to provide custom names like JSON:
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
So, is there a templating engine that is available in both Go and JavaScript, and that can handle lowercase struct properties?
As the comments above state, you can't expect any 3rd party library to be able to read lowercase properties on your struct, but it appears you are trying to use tags to represent alternative representations of your struct (as you can with the encoding/json library).
What you can do is use something like github.com/fatih/structs to convert your structs to maps and then range through to lowercase all of your keys (copying the values and removing the uppercase versions) and pass it into mustache.Render() as your context. If you want to use struct tags like the encoding/json library does, you'd have to use the reflect package and write a struct-to-map function that takes into account the tags on the struct (basic example given in the documentation here). There are some SO answers on how to write a struct-to-map function using reflection, which you can improve upon to add struct tag handling as you need.
To answer your question, I don't think this is something a current templating library does that also works with javascript, but it shouldn't be too hard to get working with mustache given the idea above.
Right now we have javascript application that gets pulled into a WKWebView. This application fires out messages via events. We wrote an intermediary layer that listens for those events, does some parsing and delivers the result to iOS to do some native work.
This works pretty well; however, we are a little worried (and have already seen) type safety issues arise. If the JS API changes then iOS needs to adapt and there is no contract in place really to confirm everything will remain working.
We came up with 2 ideas:
more unit tests to enforce the contract
using some sort of protocol buffer type strategy to ensure schema
Is there a better way? Is there a good protocol buffer example that does something like this?
One thing you could try is send all primitives as strings, and then parse them based on the key name. e.g. numUnits will always be an int, or maybe make some naming convention that would make it obvious what type the value is.
You could even make each value consist of 2 key value pairs, one for the value, one for the type. That would bloat the JSON but would make it type safe.
e.g. {"numUnits":{"value":"5", "type":"int"}}
Im creating a 8 bit unsigned javascript array:
var myArray = Uint8Array(64);
Manipulating this array on both client and server, then sending it over a socket.io connection. We are writing a game thus the data sent over the wire as small as possible. as socket.io does not support sending binary data is it worth bothering with javascript typed arrays or should we just use normal javascript arrays? will they still be smaller then a native js array?
NOTE: I will assume that by client you mean the browser. Else, please clarify with more details.
Socket.io does not support binary data, mainly because it offers different transports, and many of them do not support it.
However, native websockets DO support Blobs and ArrayBuffers.
If you really want to go with binary data for efficiency (which, I agree, is the way to go in your case), I think you should consider using websockets instead of socket.io.
The bad:
Only ~55% of users browse the web with a browser that supports websockets.
You wouldn't have the commodities socket.io offers, such as channels, emit and on methods.
The good:
Web sockets API is extremely simple.
It will be much more memory efficient. Normally your normal arrays are transferred by first making them a JSON string and then sending them back. This means you're actually sending a string representation of your array! Instead, here you will send the amount of bytes you would expect (in a more predictable manner, without checking string lengths before sending, but in a more "protocol"-ic way if desired).
If you decide to use WS, you could check this: http://www.adobe.com/devnet/html5/articles/real-time-data-exchange-in-html5-with-websockets.html
Else you can just go with JSON.
Truth be told, if you still go with JSON for socket.io and "universal" support, enable flash transport too, and disable slower transports if the game requires low latency.
I'm a fairly well versed programmer, so learning new technologies shouldn't be that big of an issue. That being said I'm currently attempting to make a card game in HTML5 using canvas/javascript etc.
The current question that I have is what to use to store instances of the cards. I was thinking about using XML to store the card data, but I'd like to limit the amount of work the browser has to do so the game runs more smoothly, I've heard JSON is a good alternative, but I'm just looking for suggestions. Thanks!
JSON is better in my opinion.
You can serialize objects to JSON at server side and send JSON string to client (browser), then your client will be able to parse JSON string into regular JavaScript object using JSON.parse.
In this way you'll not need to walk through XML to find particular nodes, but will just work with data in more convenient way using native JavaScript objects/arrays.
Also in most cases JSON will be more compact than XML so this can save bandwidth and speed-up data loading.
Also the data types stuff may be important here - JSON represents datatypes correctly (integers, booleans, floats, strings) and XML is storing them as strings so you'll need some additional attributes to set datatype during serialization and determine it during deserialization.
I am not sure how to do this without a framework, but what I would do is use Backbone.JS and create a model of what an instance would look like. Eg:{CardNumber:'2', CardColor: 'red', CardClass: 'hearts'}. Now I would create a collection to hold all these models, see backbone collections.
So I would store all this data client side, and possibly provide the user with an option to save the game, to persist this data to a database. This stores it as JSON and then when you persist it to the database, you can serialize it to get the individual components.
If you dont want to save to the db and do not want to use a framework. Try stack/queue implementations in Javascript. See:How do you implement a Stack and a Queue in JavaScript?
I hope that answers your question.
Stick to JSON because JSON is just a string representation of plain JS objects, and browsers are very comfortable with it. JS have no good XML handling and that will be too expensive.
Use HTML5 localStorage for keeping data until you really need to sync with the server. Frequent server operations will cause your game to suffer. Use bulk data transfers instead of many small server connections (for example at the start and the end).
Consider using a game library if the canvas graphics are intense. I have used http://jawsjs.com sometime back, but there should be better libs available out there. Selectively render only the dynamic objects, not everything on canvas.
JSON in conjunction with localStorage is a great way to go.
There are libraries available to serialize and deserialize Javascript objects and allow you tp store and retrieve it from localStorage. Simple Github search is a good way to start
I have read a lot about parsing JSON with Actionscript. Originally it was said to use this library. http://code.google.com/p/as3corelib/ but it seems Flash Player 11 has native support for it now.
My problem is that I cannot find examples or help that takes you from beginning to end of the process. Everything I have read seems to start in the middle. I have no real experience with JSON so this is a problem. I don't even know how to point ActionScript to the JSON file it needs to read.
I have a project with a tight deadline that requires me to read twitter through JSON. I need to get the three most recent tweets, along with the user who posted it, their twitter name and the time those tweets were posted.
The back end to this is already set up I believe by the development team here, therefor my JSON files or XML just needs to be pointed to and then I need to display the values in the interface text boxes I have already designed and created.
Any help will be greatly appreciated...I do know that there are a lot of threads on here I just do not understand them as they all have some understanding of it to begin with.
You need to:
Load the data, whatever it is.
Parse the data from a particular format.
For this you would normally:
Use URLLoader class to load any data. (Just go to the language reference and look into example of how to use this class).
Use whatever parser to parse the particular format that you need. http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/JSON.html this is the reference to JSON API, it also shows usage examples. I'm not aware of these API being in production version of the player, still there might be quite a bit of FP 10.X players out there, so I'd have a fallback JSON parser, but I would recommend using this library: http://www.blooddy.by/en/crypto/ over as3corelib because it is faster. The built-in API are no different from those you would find in browser, so if you look up JSON JavaScript entries, the use should be in general similar to Flash.
After you parse JSON format, you will end up with a number of objects of the following types: Object, Array, Boolean, Number, String. It has also literals to mean null and undefined. Basically, you will be working with native to Flash data structures, you only should take extra care because they will be dynamically constructed, meaning you may not make assumption about existence of parts of the data - you must always check the availability.
wvxvw's answer is good, but I think skips over a to be desired explanation of what JSON itself is. JSON is plain text, javascript object notation, when you read the text on screen it looks something like this
http://www.json.org/example.html
you can see a side by side JSON and XML (both plain text formats) essentially JSON is a bunch of name value pairs.
When you use JSON.parse("your JSON string goes here") it will do the conversions to AS3 "dynamic objects" which are just plain objects (whose properties can be assigned without previously being defined, hence dynamic). But to make a long story short, take the example you see in the link above, copy and paste the JSON as a string variable in AS3, use
var str:String = '{"glossary": {"title": "example glossary","GlossDiv": {"title": "S","GlossList": {"GlossEntry": {"ID": "SGML","SortAs": "SGML","GlossTerm": "Standard Generalized Markup Language","Acronym": "SGML","Abbrev": "ISO 8879:1986","GlossDef": {"para": "A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso": ["GML", "XML"]},"GlossSee": "markup"}}}}}';
var test:Object = JSON.parse(str);
method on the string, store it in a variable and use the debugger to see what the resulting object is. As far as I know there's really nothing else to JSON it's simply this format for storing data (you can't use E4X on it since it's not XML based and because of that it's slightly more concise than XML, no closing tags, but in my opionion slightly less readable... but is valid javascript). For a nice break-down of the performance gains/losses between AMF, JSON and XML check out this page: http://www.jamesward.com/census2/ Though many times you don't have a choice with regard to the delivery message format or protocol being used if you're not building the service, it's good to understand what the performance costs of them are.