A work collegue has implemented a class to load native C++ shared libraries into our Android app, he named this class 'LibLoader'. His proposed solution was to instantiate a LibLoader object every time we needed to use one of the native functions declared in the native library. I believe this is not optimum from a performance point of view so I was thinking about the best way to optimize this.
So far two solutions have come into my mind:
Make the LibLoader class a singleton
Turn the native methods into static ones so I won't even have to make an object
Considering native shared libraries are loaded through static/instace initializacion in the class, my questions are:
Which of these two approaches would be the best from a performance point of view? I need my code to be fast, I'm calling these native functions several times to compute FFTs on real time audio samples
Is there another optimum way to do this?
What happens to static/instance initialization if the native methods are converted to static ones? Will it be called every time a static method is accessed?
My code is:
public class LibLoader {
static final String TAG = "LibLoader";
static boolean armv7 ;
static
{
String arch = System.getProperty("os.arch");
//determine which library to load according to CPU type
if(arch.contentEquals("armv7l"))
{
//fftw neon compiled library functions work with armv71 and armv6
try {
System.loadLibrary("fftwfNeon_fftTwiddle"); //this won't load from any other platform
armv7 = true;
}catch (UnsatisfiedLinkError e)
{
Log.e(TAG, "Unable to load fftwfNeon_fftTwiddle library "+ e.getMessage());
}
}
else
{
try {
System.loadLibrary("fftTwiddle");
armv7 = false;
}catch (UnsatisfiedLinkError e)
{
Log.e(TAG, "Unable to load fftTwiddle library "+ e.getMessage());
}
}
}
public native void GetComplexFFtDoubleIN(double[] realIN, double[] imagIN, int fftSize, double[] TW, boolean ifftFlag);
public native void FFTWfNeonSymb(int fftSize, float[] realPart, float[] imagPart, boolean isFFT);
public native void FFTWfNeonSync(int fftSize, float[] realPart, float[] imagPart, boolean isFFT);
}
Having your methods static vs creating an instance variable for the class, does not affect CPU performance much. But these 2 implementations differs a lot in memory usage.
If it is only FFT calculations then, I would suggest to keep it static. This can keep you code free from memory leaks.
Update: Creating a singleton is between the 2 options I have explained. Here are the 3 ways you can do it in the order of memory simplicity.
All methods are static and you directly access the methods from any class you want. (Only has the class in memory)
Having a singleton variable. Creating a new variable will always return the same static variable. (Keeps the class and the static variable in memory)
Creating a new variable and deleting the memory after using the required methods in the class. (Allocates memory when needed and clears it when not in use.)
Related
I am trying to use ZMQ in an android application. Ideally, I should create the context once and term() it when the app is shutting down.
But unlike the c++ applications. There is no main() function on android. Based on the google document about the activity life cycle. The function onCreate(), onStop() can be called multiple times, the function onDestroy() is only called by system.
Solution1: create/destroy ZMQ context in an asyncTask(). But that would be very expensive.
Solution2: based on the thread Android global variable, I could create a global ZMQ.Context contextvariable. The problem of this method is: there is not proper function to call context.term();.
solution3. Creating a singleton class
import org.zeromq.ZMQ;
public class ZmqHelper {
private static ZMQ.Context _context;
public static ZMQ.Context createContext(){
return getContext();
}
public static ZMQ.Context getContext(){
if(_context == null) {
_context = ZMQ.context(1);
}
return _context;
}
private ZmqHelper(){
}
public static boolean release(){
// make sure all sockets are closed
if(_context != null) {
_context.term();
_context = null;
return true;
}
return false;
}
}
The problem of the singleton is same as solution 2. I have to manually call ZmqHelper.release() //which calls context.term() in some stage. I am not sure where is the good place to invoke the function term() to destroy zmq context.
So what is the correct way to create/terminate a ZMQ context in an android application?
env:
Ubuntu: 16.04 LTS
Android studio: 2.3.3
ZMQ: org.zeromq:jeromq:0.4.0
I think you shall use a singletone instance as more straightforward solution.
All network communication on Android must be held is a separate thread (not UI-thread). So you may term ZMQ.Context when you interrupt the networking thread. If your app doesn't need background network connection (you perform netwroking only at separate Activities) it's better to term ZMQ.Context in onPause() methods of those Activities for performance reasons.
I am using such approach but meet problems with terminating SUB socket. Though I think the approach is pretty well.
I am currently migrating I game I made in Cocos2d-X 2.2.6 to the latest version: Cocos2d-X 3.10, however I have a question about the memory management: I have created a lot of my own classes that inherit from CCObject (I have used a lot of XX::create(), xx->retain() and xx->release() methods to create and destroy objects), however since this class has been deprecated, what should I use in its place?
I guess my question is how can I do the memory management of a custom class in Cocos2d-X version 3?
I'm developing cocos2d-x games now.
As Mr.Zen commented, your class should inherit from cocos2d::Ref.
And member variables, use cocos2d::RefPtr.
It makes memory management easier, manages reference count automatically.
You don't need to worry about retain or release after the instance created.
Here is the snippet.
Sample.h
class Sample : public cocos2d::Ref
{
public:
Sample();
~Sample();
void hoge();
}
UseSample.h
class UseSample : public cocos2d::Ref
{
private:
cocos2d::RefPtr<Sample> sample { nullptr };
void createSample();
void useSample();
}
UseSample.cpp
void UseSample::createSample()
{
this->sample = Sample::create(); // RefPtr increases sample retain count;
}
void UseSample::useSample()
{
this->sample->hoge();
}
Hope this can helps.
Here is what I want to achieve:
I am building an Android-Application which needs to be plugin-aware. What I need to do is downloading .java files from a Web-Server and then compile them at runtime within my application and then load it into the classpath. I want to use Java because of the ease of use because I can use the plugin objects just like my stock ones.
I've seen javax.tools's way of compiling but that's not available on DalvikVM. What are the best alternatives to that (that work in a similar way)?
EDIT:
I am using .bsh-script now. This works like a charm on a JVM and should work on an Android device (which I will test next):
package de.hotware.beanshell.test;
import bsh.EvalError;
import bsh.Interpreter;
public class BeanShellTest {
public static interface InterfaceTest {
public void sayHello();
}
public static void main(String[] args) {
try {
Interpreter interpreter = new Interpreter();
InterfaceTest res = (InterfaceTest) interpreter.eval("import de.hotware.beanshell.test.BeanShellTest.InterfaceTest;" +
"new InterfaceTest() {" +
"public void sayHello() { System.out.println(\"hello\");}" +
"}");
res.sayHello();
} catch(EvalError e) {
e.printStackTrace();
}
}
public void test() {
}
}
You need to do two things:
Everything you would do if you were running inside a JVM. Download the source, compile it into .class files with javac or equivalent.
Convert the class files to DEX format. This would mean running the dx program on the device, which is doable, but it can be a bit memory-hungry, especially for larger programs.
Once you've done that, you can use DexClassLoader to load the code from the DEX file.
All things considered, I think you're better off with BeanShell.
I have an app which uses Google Maps (v1) and from the crash reports, I am seeing this exception from time to time:
java.lang.NoClassDefFoundError: android.security.MessageDigest
at com.google.android.maps.KeyHelper.getSignatureFingerprint(KeyHelper.java:60)
at com.google.android.maps.MapActivity.createMap(MapActivity.java:513)
at com.google.android.maps.MapActivity.onCreate(MapActivity.java:409)
I have defined
<uses-library
android:name="com.google.android.maps"
android:required="true" />
inside the application tag and I am extending MapActivity as well. The application works fine on most devices but there are some uncommon ones that report this exception, usually on Android 4.0.4 like Woxter Tablet PC 90BL, TAB9008GBBK and other generic names.
From what I read in Stackoverflow, it is a problem in the ROM and it can be solved by the user doing some advanced tricks but what I want is to prevent this crash, as I don't think it can be solved, I just want to inform the user (and thell him to buy a better device :) and disable maps functionality instead of crashing. But I can't find a way to handle this error or test it with the devices I have.
Also my main activity is based on MapActivity so I don't know how can I handle this exception before opening it.
Disclaimer: I've not come across this error on any of my apps / devices but I solved a similar problem. May be that same technique can help you.
Given that the class is either unavailable or an exception occurrs while loading the class, why not try to force load it when your application starts ? Class.forName("android.security.MessageDigest") should load the class and you can catch the Error thrown from that call. I know its dirty, but it should work. You can declare a custom Application class on the manifest to make this check.
Class loading test
try
{
Class.forName("android.security.MessageDigest");
}
catch (Throwable e1)
{
e1.printStackTrace();
//Bad device
}
You can also perform a litmus test and check the functionality of the class should the class loading succeed by digesting a simple String.
Functional test
try
{
MessageDigest digester = MessageDigest.getInstance("MD5");
digester.update("test".getBytes("UTF-8"));
byte[] digest = digester.digest();
}
catch (Throwable e1)
{
e1.printStackTrace();
// Class available but not functional
}
If the class loading / litmus test fails, update a shared preference flag and let the user know that his device sucks :)
Try to change the import android.security.MessageDigest to java.security.MessageDigest
by the look at this link:
What is 'android.security.MessageDigest''?
It looks that the android.security.MessageDigest was remove from Honeycomb so change it to the java one. and check this link as well:
http://productforums.google.com/forum/#!category-topic/maps/google-maps-for-mobile/KinrGn9DcIE
As been suggested there by #XGouchet:
Try downloading the latest version of the Google Maps API and rebuild your application with targetSDK set to the highest available (as of today it should be 17 / Jelly Bean).
The class android.security.MessageDigest is an abstract class (see MessageDigest API) what means that it can't be instantiated right away. So what happens is, that any time a device/app can't find an implementation of this class you will get the exception above, namely
java.lang.NoClassDefFoundError: android.security.MessageDigest
It's a good question why this happens. May be some phone vendors didn't ship their phone with the required library that actually implements this abstract class. I faced a similar issue with the TUN.ko module in the past.
Approach 1
What should help is, if you provide your own (empty) implementation of this class that "implements" the abstract classes and methods like this:
public class MessageDigestSpi extends Object {
byte[] engineDigest() { return new byte[0]; }
void engineReset() { }
void engineUpdate(byte[] input, int offset, int len) { }
}
public class MessageDigest extends MessageDigestSpi {
}
... and put those classes into the folder <src>/java/security/. So this way you provide your own implementation that is always found and might contain some code in order to inform the user or provide an alternative implementation.
So the remaining questions are: what does the app do, if the implementation is provided by the system, too and how to control that the system implementation is the first choice?
The answer: which implementation is chosen depends on the import order. Looking at Eclipse you can define the order in the project properties, Java build path, tab order and export. Be sure that you have any system libraries on top that might include the system implementation (most likely the Android libraries). This way the system searches in those libraries first. If nothing is found your classes get loaded and executed.
Approach 2
As an alternative to the implementation in an own abstract class you could of course simply instantiate the MessageDigest class, catch the NoClassDefFoundError exception and store the result for later evaluation:
import android.security.MessageDigest;
public class MessageDigestTester {
private static Boolean messageDigestAvailable = null;
public static Boolean isLibraryAvailable() {
if (messageDigestAvailable == null) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
messageDigestAvailable = true;
} catch (NoClassDefFoundError e) {
messageDigestAvailable = false;
}
}
return messageDigestAvailable;
}
}
Then use if (MessageDigestTester.isLibraryAvailable()) { } else { } in your code in order to encapsulate the usage of this library and to provide an alternative.
Approach two is easier to implement whereas approach one is the more sophisticated solution.
Hope this was helpful ... Cheers!
I doubt if there is a way to make compile-time conditions in Java like #ifdef #ifndef in C++.
My problem is that have an algorithm written in Java, and I have different running time improves to that algorithm. So I want to measure how much time I save when each improve is used.
Right now I have a set of boolean variables that are used to decide during the running time which improve should be used and which not. But even testing those variables influences the total running time.
So I want to find out a way to decide during the compilation time which parts of the program should be compiled and used.
Does someone knows a way to do it in Java. Or maybe someone knows that there is no such way (it also would be useful).
private static final boolean enableFast = false;
// ...
if (enableFast) {
// This is removed at compile time
}
Conditionals like that shown above are evaluated at compile time. If instead you use this
private static final boolean enableFast = "true".equals(System.getProperty("fast"));
Then any conditions dependent on enableFast will be evaluated by the JIT compiler. The overhead for this is negligible.
javac will not output compiled code that is unreachable. Use a final variable set to a constant value for your #define and a normal if statement for the #ifdef.
You can use javap to prove that the unreachable code isn't included in the output class file. For example, consider the following code:
public class Test
{
private static final boolean debug = false;
public static void main(String[] args)
{
if (debug)
{
System.out.println("debug was enabled");
}
else
{
System.out.println("debug was not enabled");
}
}
}
javap -c Test gives the following output, indicating that only one of the two paths was compiled in (and the if statement wasn't):
public static void main(java.lang.String[]);
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3; //String debug was not enabled
5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
I think that I've found the solution, It's much simpler.
If I define the boolean variables with "final" modifier Java compiler itself solves the problem. Because it knows in advance what would be the result of testing this condition.
For example this code:
boolean flag1 = true;
boolean flag2 = false;
int j=0;
for(int i=0;i<1000000000;i++){
if(flag1)
if(flag2)
j++;
else
j++;
else
if(flag2)
j++;
else
j++;
}
runs about 3 seconds on my computer.
And this one
final boolean flag1 = true;
final boolean flag2 = false;
int j=0;
for(int i=0;i<1000000000;i++){
if(flag1)
if(flag2)
j++;
else
j++;
else
if(flag2)
j++;
else
j++;
}
runs about 1 second. The same time this code takes
int j=0;
for(int i=0;i<1000000000;i++){
j++;
}
Never used it, but this exists
JCPP is a complete, compliant,
standalone, pure Java implementation
of the C preprocessor. It is intended
to be of use to people writing C-style
compilers in Java using tools like
sablecc, antlr, JLex, CUP and so
forth. This project has has been used
to successfully preprocess much of the
source code of the GNU C library. As
of version 1.2.5, it can also
preprocess the Apple Objective C
library.
http://www.anarres.org/projects/jcpp/
If you really need conditional compilation and you use Ant, you might be able to filter your code and do a search-and-replace in it.
For example: http://weblogs.java.net/blog/schaefa/archive/2005/01/how_to_do_condi.html
In the same manner you can, for example, write a filter to replace LOG.debug(...); with /*LOG.debug(...);*/. This would still execute faster than if (LOG.isDebugEnabled()) { ... } stuff, not to mention being more concise at the same time.
If you use Maven, there is a similar feature described here.
If you use IntelliJ there is a plugin called Manifold, that - along with many other features - allows one to use #ifdef and #define in Java.
Plugin url:
https://manifold.systems/
Preprocessor information:
https://github.com/manifold-systems/manifold/tree/master/manifold-deps-parent/manifold-preprocessor
PS: I am not affiliated with them, we just happen to use it, and it helps a lot with out workflow (which is likely NOT typical for Java development)
Use the Factory Pattern to switch between implementations of a class?
The object creation time can't be a concern now could it? When averaged over a long running time period, the biggest component of time spent should be in the main algorithm now wouldn't it?
Strictly speaking, you don't really need a preprocessor to do what you seek to achieve. There are most probably other ways of meeting your requirement than the one I have proposed of course.
final static int appFlags = context.getApplicationInfo().flags;
final static boolean isDebug = (appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0