Android performance getJSONObject while parsing - android

I'm currently parsing JSON and got the following piece of code:
boolean suf = list.getJSONObject(i).getBoolean("sufficient");
String grade = list.getJSONObject(i).getString("grade");
String id= list.getJSONObject(i).getString("id");
I'm wondering if multiple times calling getJSONObject creates overhead resulting in increasing processing time.
Would this be faster and/or better for example?
JSONObject object = list.getJSONObject(i);
boolean suf = object.getBoolean("sufficient");
String grade = object).getString("grade");
String id= object.getString("id");
This does introduce a new object, but will the next 3 calls make the tradeoff worth it?
Since I'm showing a dialog to inform the user something is loading (and thus they can't undertake any action), I'd like to minimize the wait time for the user.

2nd option is how I usually do. But you will hardly see any notice in performance.
list.getJSONObject(i).getBoolean("sufficient"); creates a temporary object and gets the value. Now a days, compilers are smart enough to store that temporary objects just in case them. Even if they don't, unless you are handling some millions of jsonobjs in your "list", I don't see any performance impact here.

Related

What is the most efficient way to process a multiple value method return?

I have a method that returns Point:
private Point getDisplayWH() {
Display display = this.getWindowManager().getDefaultDisplay();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
Point realWH = new Point();
display.getSize(realWH);
return realWH;
}
return new Point(display.getWidth(), display.getHeight());
}
Now, when receiving this result, I can't decide which of these two is more efficient.
Number 1:
Point displayWH = getDisplayWH();
layoutPreviewDim = calcCamPrevDimensions(displayWH.x, displayWH.y));
Number 2:
layoutPreviewDim = calcCamPrevDimensions(getDisplayWH().x, getDisplayWH().y));
In this article it is said that:
If you have a method returning a string, and you know that its result will always be appended to a StringBuffer anyway, change your signature and implementation so that the function does the append directly, instead of creating a short-lived temporary object.
But should I follow these instructions even if I have to call the method more than once to get the return? What about display variable in my getDisplayWH() method? Is it more efficient approach than accessing Display methods directly this.getWindowManager().getDefaultDisplay().xxxx?
And my second side question: Is there a general way to check/compare code efficiency other than with system time difference before and after method call? Or the time difference is the ultimate tool?
Calling a method twice rather than storing the return value is going to be inefficient.
One way to test for efficiency is to write a unit test and perhaps use the two approaches, call them 10k times in a loop, and see what happens.
But, regardless, try to minimize calling methods multiple times, if they return the same value on each call.
The point about the string is that strings have to be garbage collected, as they are not appended to. So you create extra objects that will need to be collected. So, appending it directly to the StringBuffer just makes sense to limit how long the garbage collector runs.
If you go with the unit test approach, you can also monitor garbage collection to see what the difference is.
One way to monitor garbage collection is to follow this article:
http://www.raizlabs.com/dev/2014/04/hunting-your-leaks-memory-management-in-android-part-2-of-2/
Once way is to use DDMS and cause a garbage collection to see how much memory has been allocated, but there are other approaches.

Decode complex JSON string to various object(s)

I was just wondering if anyone could recommend a better alternative method than org.json for decoding a complex JSON string. For reference, this will be coming from a web server down to Android (& iOS, but that's the other dev's problem!) devices, it doesn't have to go back up.
The string is of the following nature...
{"header":"value","count":value, ..., "messages":[
{"messagetype":1,"name":"value"},
{"messagetype":2,"name":"value","name":value},
{"messagetype":1,"name":"value"},
{"messagetype":3,"name":"value","subvalues":["value",value,value]},
...
{"messagetype":4,"name":value,"name":"value","name":value}
]}
Basically, there are some header fields which I can always rely on but then there will be an "array" of messages, variable in count, content and order.
I've been researching this for a few days now and have dismissed GSON and a few others because that either need to know the exact structure in advance and/or don't deal well with the embedded types (the contained messages).
Answer three in this question pointed me to using the org.json library and I know I can use that to parse through the string but I guess one of that answer's replies ("That's super old school and nobody uses that library anymore in the real world") has made me question my approach.
Can anyone suggest a library/approach which would handle this problem better? If anyone else has used an alternative approach to dealing with this type of complex and variable structure, I'd really appreciate your input.
Thanks in advance.
I really do not agree with the opinion about org.json libray: "That's super old school and nobody uses that library anymore in the real world", since parsing json by using this library is pretty straightforward. Besides, how complex can json get?, I mean, is all about key/value pairs, nothing that can't be solved with a few lines of code, for instance I will illustrate you a few cases, so that you'll get convinced that is pretty simple to do:
Suppose you have a response from the server containing all info you need formatted in a json array, then you can do something like this to parse the String:
JsonArray arrayJson = new JsonArray(response);
But now you want to access arrayJson childs:
for (int i = 0; i < arrayJson.length() - 1; i++)
{
JsonObject json = arrayJson.getJSONObject(i);
}
And now assume you have another array of json's inside those you retrieved in the for loop:
Then you'll get them this way:
for (int i = 0; i < arrayJson.length() - 1; i++)
{
JsonObject json = arrayJson.getJSONObject(i);
JSONArray anotherArray = json.getJSONArray("key");
}
....., more nestings you can handle them the same way, so I think I established my point. Remember that sometimes, struggling on finding easier ways to do things, can get them even harder to do.

Excessive garbage collection in arithmetic evaluator

I'm attempting to create an Android app which graphs simple mathematical functions that the user inputs (essentially a graphing calculator).
Every onDraw call requires hundreds of arithmetic evaluations per second (which are plotted on screen to produce the graph). When my code evaluates the expression the program slows down considerably, when the inbuilt methods evaluate the expression, the app runs with no issue.
According to 'LogCat', garbage collection occurs about 12 times per second, each time pausing the app for roughly 15 milliseconds, resulting in a few hundred milliseconds worth of freezes every second. I think this is the problem.
Here is a distilled version of my evaluator function. The expression to be evaluated is named "postfixEquation", the String ArrayList "list" holds the final answer at the end of the process. There are also two String arrays titled "digits" and "operators" which store the numbers and signs which are able to be used:
String evaluate(String[] postfixEquation) {
list.clear();
for (int i = 0; i < postfixEquation.length; i++) {
symbol = postfixEquation[i];
// If the first character of our symbol is a digit, our symbol is a numeral
if (Arrays.asList(digits).contains(Character.toString(symbol.charAt(0)))) {
list.add(symbol);
} else if (Arrays.asList(operators).contains(symbol)) {
// There must be at least 2 numerals to operate on
if (list.size() < 2) {
return "Error, Incorrect operator usage.";
}
// Operates on the top two numerals of the list, then removes them
// Adds the answer of the operation to the list
firstItem = Double.parseDouble(list.get(list.size() - 1));
secondItem = Double.parseDouble(list.get(list.size() - 2));
list.remove(list.size() - 1);
list.remove(list.size() - 1);
if (symbol.equals(operators[0])){
list.add( Double.toString(secondItem - firstItem) );
} else if (symbol.equals(operators[1])) {
list.add( Double.toString(secondItem + firstItem) );
} else if (symbol.equals(operators[2])) {
list.add( Double.toString(secondItem * firstItem) );
} else if (symbol.equals(operators[3])) {
if (firstItem != 0) {
list.add( Double.toString(secondItem / firstItem) );
} else {
return "Error, Dividing by 0 is undefined.";
}
} else {
return "Error, Unknown symbol '" + symbol + "'.";
}
}
}
// The list should contain a single item, the final answer
if (list.size() != 1) {
return "Error, " + list has " + list.size() + " items left instead of 1.";
}
// All is fine, return the final answer
return list.get(0);
}
The numerals used in the operations are all Strings, as I was unsure if it was possible to hold multiple types within one array (i.e. Strings and Doubles), hence the rampant "Double.parseDouble" and "Double.toString" calls.
How would I go about reducing the amount of garbage collection that occurs here?
If it's of any help, I have been using these steps to evaluate my postfix expression: http://scriptasylum.com/tutorials/infix_postfix/algorithms/postfix-evaluation/index.htm.
I have been unable to get past this issue for weeks and weeks. Any help would be appreciated. Thanks.
The rule for tight loops in Java is don't allocate anything. The fact that you're seeing such frequent GC collections is proof of this.
You appear to be doing calculations with Double, then converting to a String. Don't do that, it's terrible for performance because you create tons and tons of strings then throw them out (plus you are converting back and forth between strings and doubles a lot). Just maintain an ArrayDeque<Double> and use it as a stack -- this also saves you from doing the array resizes that are probably also killing performance.
Precompile the input equations. Convert all the input operations to enum instances -- they are faster to compare (just takes a switch statement), and may even use less memory. If you need to handle doubles, either use a generic Object container and instanceof, or a container class that contains both an operation enum and a double. Precompiling saves you from having to do expensive tests in your tight loop.
If you do these things, your loop should positively fly.
Probably your list manipulation is the source of this problem. Lists internally have arrays, which are expanded/shrunk depending on how much data is on the list. So doing lots of add and removes randomly will heavily require garbage collection.
A solution to avoid this is using the right List implementation for your problem, allocate enough space to the list at the beginning to avoid resizing the internal array and to mark unused elements instead of removing them
The freezing symptoms are because you're doing your calculations in your UIThread. If you don't want your app to freeze, you might want to check AsyncTask to do calculations on a separate thread.
PS: also looks like you're doing some useless operations in there... why parseDouble() secondItem?
The 15ms pauses are not occurring in your UI thread, so they should not be affecting performance to much. If your UI is pausing while your method is executing, consider running it on another thread (with AsyncTask)
To reduce your garbage collection you need to reduce the amount of memory allocated within the loop.
I would suggest looking at:
Performing the Arrays.asList functions outside the loop (ideally somewhere that is only executed once such as your constructor or a static constructor)
If your list is a LinkedList, consider changing it to an ArrayList
If your List is an ArrayList, make sure you initialise it with enough capacity so it won't need to be resized
Consider making your List store Objects rather than Strings, then you can store both your symbols and Doubles in it, and don't need to convert back and forward from Double to String as much
Consider writing a proper parser (but this is a'lot more work)
However, you are using a lot of strings. While this may not be the case, it's always one of those things you can check out because Java does funky stuff with String. If you are having to convert the string to double as you are outputting, then there's quite a bit of overhead going on.
Do you need to store the data as String? (Note that the answer may actually be yes) Heavy use of temporary strings can actually cause the garbage collector to get fired off often.
Be careful about premature optimization. Profilers and running through the function line-by-line can help

Android How to Change Many Class Variables Efficiently? (Maybe I'm Bastardizing OOP?)

I have an Android Class called Receipt, it's modeled off a typical Receipt you'd get in a retail environment and includes the following Class variables:
receipt_number
date_ordered
date_paid
item_quantity
item_type
item_sku
item_price
total_price
customer_id
customer_name
clerk_id
clerk_name
Whew... there's a lot. I'm just becoming accustom to OOP and while I love the idea of using a Receipt data Class to store the properties of a Receipt, I fear I am using an object just for the sake of using an object and not using data Classes appropriately.
Why? Well, I have another method in another Class which I feed my Receipt object to. Once fed to this other Class, the Receipt data is used to fill out a View which allows the user to edit said Receipt (data from the Receipt fills out EditText boxes which can be changed, then saved). The problem is that the code is getting ridiculous for updating a Receipt. I've got a helper method in Receipt for virtually every variable above (e.g. setClerkId(), setCustomerName(), setItemSku(), etc. etc.) and when I update a Receipt, I find myself calling all these methods and it's turning into a huge rats nest.
Surely I am missing the boat here, and probably by a long-shot. There must be a more sane way to feed in all the values of my new Receipt (it's really an update of the old object) without manually updating each variable using a helper method? I guess I'd be a little bit surprised (no, a lot surprised) if this is the correct way of doing this.
Any push in the right direction would be much appreciated!
Thanks!
You are doing it right I guess. I an object has a lot of named properties then you'll have to do a lot of get/set.
You can simplify that if you don't need to access each individually if you put them all into single (or several) ArrayList<String>/String[] or even other objects. Whatever you feel is an appropriate representation of your data.
Or you take a HashMap instead of your class and store them like so:
HashMap<String, String> hashmap = new HashMap<String, String>();
hashmap.put("receipt_number", value);
String value = hashmap.get("receipt_number");
That results in a more dynamic way to store values.

Optimization of JSON parsing on Android

I'm developping an app for Android that needs to get an important amount of data from a JSON feed. This feed is a one line JSON file, weighting approx 400 ko, containing approximately 10 arrays that I need to get.
I'm using the JSON library for Android to do so, and the output works well, but it takes ages (well, 30 secs approx) to compute. The download step is done quickly, that's the creation of the JSON objects that seems to be very long. Here are my steps (removing try/catch blocks and so on).
JSONObject feed = new JSONObject(big_string_from_feed);
JSONArray firstArray = feed.getJSONArray("key1");
JSONArray secondArray = feed.getJSONArray("key2");
[...]
And after i go through all my arrays to get every element the following way :
for (int currentIndex =0;currentIndex<firstArray.length();currentIndex++){
JSONObject myObject = firstArray.getJSONObject(currentIndex);
[....]
}
Is there something wrong in the way I do this ? Is there a better way to do it ?
Thank you very much in advance.
If performance is a concern, use Jackson. See https://github.com/eishay/jvm-serializers/wiki for performance results. (These results should be updated soon to include Jackson manual/tree-strings processing, which will have performance somewhere between Jackson manual and Jackson databind-strings processing. Manual/tree-strings processing is the approach demonstrated in the original question.)
Look at json-simple (see http://code.google.com/p/json-simple). It provides SAX style parsing of JSON streams, and is faster.

Categories

Resources