Android - slow memory allocation for big count of objects - java

I have app for android, where I need to load some file and process every string in that file and works further with this processed strings.
So I created class Entry for processed line and holder for this Entries - class EntryManager, which looks like this:
public class EntryManager {
private static EntryManager instance;
private List<Entry> rules = new ArrayList<>();
public static synchronized EntryManager getInstance() {
if (instance == null) {
instance = new EntryManager();
}
return instance;
}
public void addRule(String rule) {
rules.add(RulesParser.parseRule(rule));
}
public void clear() {
rules.clear();
}
}
Entry class is quite simple - it contains original String line and few boolean flags. General count of entries is ~70'000, so will be created 70'000 objects.
The problem is:
the first time it takes 0.3 seconds to finish, but all other times it takes ~7 seconds. Is is possible to avoid without using NDK?
UPD. Looks like it was my fail - during testing my phone was connected to PC via cable, when I took it out everything became ok

Related

Concept to create thread wide/class wide object

I'm searching for a concept to forward an object to subobjects.
Example:
I would like to create log files for several main Objects, that include sub objects (imagine a REST server that would log every single connection by ID).
Creating one big log file is simple ( redirect System.out.println, I already encapsulated that)
Example code:
class SubElementA{
public SubElementA(){
Debugger.debug("I am called, too");
}
}
Application.java
package com.dev4ag;
class Application{
private ElementA elA;
private String prefix;
public Application(String name){
this.elA = new ElementA();
this.prefix = name;
}
public void countUp(){
Debugger.debug(this.prefix+": I will now count up");
this.elA.doSomeStuff();
}
}
ElementA.java
package com.dev4ag;
class ElementA{
private int counter;
private SubElementA subElementA;
public void doSomeStuff(){
counter++;
Debugger.debug("Counter is: "+counter);
}
//Constructor
public ElementA(){
subElementA = new SubElementA();
this.counter = 0;
};
}
SubElementA.java
package com.dev4ag;
class SubElementA{
public SubElementA(){
Debugger.debug("I am called, too");
}
}
Debugger.java
package com.dev4ag;
public class Debugger {
public static void debug(String output){
//Just imagine we would write to a file here ;)
System.out.println(output);
}
}
(it was more easy to write system.out.println than to create a file, just imagine, Debugger.debug would write to a file).
Now I am thinking about a solution to create one Debug output target for each App. I could definitely change debug to not being static and create a debug object within Application.
But is there any way to use this object in the sub classes without forwarding the debug object either through Constructor or setter function, which would mean to have to add an object for the debugger to each class?
What would be the most beautiful solution for that?
Note that this solution might decrease performance a lot and it is pretty dirty way, but some loggers include such data.
But you can use Thread.currentThread().getStackTrace() to get stacktrace like in error and get class and method from where your method was called.
If you are using java9+ then you should probably use StackWalker API instead, especially that it have nice filters and other useful features.
So then you could guess app by class/method names on the stack.

Buffer and flush Apache Beam streaming data

I have a streaming job that with initial run will have to process large amount of data. One of DoFn calls remote service that supports batch requests, so when working with bounded collections I use following approach:
private static final class Function extends DoFn<String, Void> implements Serializable {
private static final long serialVersionUID = 2417984990958377700L;
private static final int LIMIT = 500;
private transient Queue<String> buffered;
#StartBundle
public void startBundle(Context context) throws Exception {
buffered = new LinkedList<>();
}
#ProcessElement
public void processElement(ProcessContext context) throws Exception {
buffered.add(context.element());
if (buffered.size() > LIMIT) {
flush();
}
}
#FinishBundle
public void finishBundle(Context c) throws Exception {
// process remaining
flush();
}
private void flush() {
// build batch request
while (!buffered.isEmpty()) {
buffered.poll();
// do something
}
}
}
Is there a way to window data so the same approach can be used on unbounded collections?
I've tried following:
pipeline
.apply("Read", Read.from(source))
.apply(WithTimestamps.of(input -> Instant.now()))
.apply(Window.into(FixedWindows.of(Duration.standardMinutes(2L))))
.apply("Process", ParDo.of(new Function()));
but startBundle and finishBundle are called for every element. Is there a chance to have something like with RxJava (2 minute windows or 100 element bundles):
source
.toFlowable(BackpressureStrategy.LATEST)
.buffer(2, TimeUnit.MINUTES, 100)
This is a quintessential use case for the new feature of per-key-and-windows state and timers.
State is described in a Beam blog post, while for timers you'll have to rely on the Javadoc. Nevermind what the javadoc says about runners supporting them, the true status is found in Beam's capability matrix.
The pattern is very much like what you have written, but state allows it to work with windows and also across bundles, since they may be very small in streaming. Since state must be partitioned somehow to maintain parallelism, you'll need to add some sort of key. Currently there is no automatic sharding for this.
private static final class Function extends DoFn<KV<Key, String>, Void> implements Serializable {
private static final long serialVersionUID = 2417984990958377700L;
private static final int LIMIT = 500;
#StateId("bufferedSize")
private final StateSpec<Object, ValueState<Integer>> bufferedSizeSpec =
StateSpecs.value(VarIntCoder.of());
#StateId("buffered")
private final StateSpec<Object, BagState<String>> bufferedSpec =
StateSpecs.bag(StringUtf8Coder.of());
#TimerId("expiry")
private final TimerSpec expirySpec = TimerSpecs.timer(TimeDomain.EVENT_TIME);
#ProcessElement
public void processElement(
ProcessContext context,
BoundedWindow window,
#StateId("bufferedSize") ValueState<Integer> bufferedSizeState,
#StateId("buffered") BagState<String> bufferedState,
#TimerId("expiry") Timer expiryTimer) {
int size = firstNonNull(bufferedSizeState.read(), 0);
bufferedState.add(context.element().getValue());
size += 1;
bufferedSizeState.write(size);
expiryTimer.set(window.maxTimestamp().plus(allowedLateness));
if (size > LIMIT) {
flush(context, bufferedState, bufferedSizeState);
}
}
#OnTimer("expiry")
public void onExpiry(
OnTimerContext context,
#StateId("bufferedSize") ValueState<Integer> bufferedSizeState,
#StateId("buffered") BagState<String> bufferedState) {
flush(context, bufferedState, bufferedSizeState);
}
private void flush(
WindowedContext context,
BagState<String> bufferedState,
ValueState<Integer> bufferedSizeState) {
Iterable<String> buffered = bufferedState.read();
// build batch request from buffered
...
// clear things
bufferedState.clear();
bufferedSizeState.clear();
}
}
Taking a few notes here:
State replaces your DoFn's instance variables, since
instance variables have no cohesion across windows.
The buffer and the size are just initialized as needed instead
of #StartBundle.
The BagState supports "blind" writes, so there doesn't need to be
any read-modify-write, just committing the new elements in the same
way as when you output.
Setting a timer repeatedly for the same time is just fine;
it should mostly be a noop.
#OnTimer("expiry") takes the place of #FinishBundle, since
finishing a bundle is not a per-window thing but an artifact of
how a runner executes your pipeline.
All that said, if you are writing to an external system, perhaps you would want to reify the windows and re-window into the global window before just doing writes where the manner of your write depends on the window, since "the external world is globally windowed".
The documentation for apache beam 0.6.0 says that StateId is "Not currently supported by any runner."

Static variables, pattern and Android performance

I'm doing some big refactoring operations relative to some performance improvements in an android app which is using a class with lot of static variables and even static activity references which are then use through the app ! So I was looking for some best practices in Android to store data and give to these data a global access in my app.
First I removed all the activity references to avoid any memory leak, but I'm still looking to know what is the best practice regarding static variables which need to be used anywhere in the android app.
I read many times (example1, exemple2) : using static variables is not necessary a good practices and it's better/cleaner to use one singleton class with getter and setter to have access to my global variables whatever the activity where I am. So what I've started to think is a class which could looks like this one :
public class AppSingleton extends Application {
private static AppSingleton appInstance;
// different stored data, which could be relative to some settings ..
private String setting1;
private String setting2;
private AppSingleton() {
super();
appInstance = new AppSingleton();
}
public static AppSingleton getAppInstance() {
if (appInstance == null) {
appInstance = new AppSingleton();
}
return appInstance;
}
// Getter and Setter for global access
public String getSetting1() {return setting1;}
public void setSetting1(String setting1) {this.setting1 = setting1;}
public String getSetting2() {return setting2;}
public void setSetting2(String setting2) {this.setting2 = setting2;}
}
Then I can use for example :
// Get the application instance
AppSingleton appS = (App) getApplication();
// Call a custom application method
appS.customAppMethod();
// Call a custom method in my App singleton
AppSingleton.getInstance().customAppSingletonMethod();
// Read the value of a variable in my App singleton
String var = AppSingleton.getInstance().getCustomVariable;
For me AppSingleton sounds good because this singleton which restrics ths instantiation of this class to one object, also this class is not destroyed until there are any undestroyed Activity in the application so it means I can keep my global data in the current lifecycle of my app for example from a 'Log in'. But also I can maintain the state of my global variables from my getters/setters.
But then I also had a look on the official android documentation about Performance Tips which say it's good to use static variable it's faster and don't forget to avoid internal getter and setter it's too expansive !
I'm a bit confused about all of these and I'm really keen to learn more about that topic. What is the best practices about using one class to provide an access to some variables which are needed in different part of my code ? Is the class above AppSingeleton is something which could be interesting to use in terms of architecture and performance ?
Is it a good idea to use a singleton pattern for managing global variables in android ?
those lines are completely wrong on your code:
private AppSingleton() {
super();
appInstance = new AppSingleton();
}
public static AppSingleton getAppInstance() {
if (appInstance == null) {
appInstance = new AppSingleton();
}
return appInstance;
}
you cannot instantiate new Application, the Android framework instantiates it. Change to this:
private AppSingleton() {
super();
appInstance = this; // keep ref to this application instance
}
public static AppSingleton getAppInstance() {
return appInstance;
}
Regarding the accessing of global variables. I believe it's more organized to have those singletons somewhere else on your application. The application class have different responsibilities you should not overload it with different tasks. That's OO clean coding.
Also, sometimes there's not that much reason in an Android app to have getters/setters for everything, because u don't need as much access control as in bigger projects. But this should be considered case-by-case about the necessity and not be used a general rule.
So you could for example have it like:
public class Globals {
private static final Globals instance = new Globals();
public static Globals get() { return instance; }
public String value1 = "Hello"
public int value2 = 42;
}
then on your code call as needed:
Log.d(TAG, Globals.get().value1);
Globals.get().value1 = "World";
Log.d(TAG, Globals.get().value1);
Log.d(TAG, "Value2 = " + Globals.get().value2);

WebDriver datadriven (using TestNG) scripts takes a long time to start

I have extended Selenium using the Java WebDriver library and the TestNG framework. When running test scripts, I notice an inordinate amount of time for the test to start execution, when the test takes in input parameters from an Excel file (using the #DataProvider annotation).
The delay can amount to about 10 min, which makes it time consuming to run and debug. Is there a reason for this significant delay?
Yes could be because of the way you are reading from excel (greedy data provider) and depends on how big your excel file is. There is something called lazy data provider. Found an example of one here . Posting the code from the link.
For better understanding need to see your code.
public class LazyDataProviderExample {
#Test(dataProvider = "data-source")
public void myTestMethod(String info) {
Reporter.log("Data provided was :" + info, true);
}
#DataProvider(name = "data-source")
public Iterator<Object[]> dataOneByOne() {
return new MyData();
}
private static class MyData implements Iterator<Object[]> {
private String[] data = new String[] { "Java", "TestNG", "JUnit" };
private int index = 0;
#Override
public boolean hasNext() {
return (index <= (data.length - 1));
}
#Override
public Object[] next() {
return new Object[] { data[index++] };
}
#Override
public void remove() {
throw new UnsupportedOperationException("Removal of items is not supported");
}
}
}
For some reason, this issue was resolved by rebuilding my custom Firefox profile - it may have gotten corrupt.
Just posting this as an answer for reference, in case any one is bogged down by this issue.

get a thread from another class

I have a java class:
public class httpd implements Runnable
{
public void createHttpdStatistics
{
httpdStatistics stats = new httpdStastics(this);
}
}
Now I would get in another class the object stats created inside httpd. When httpd object starts, it execute in the jvm. I tought to build get method inside httpd class but when I'm in the other class how I get the exact httpd object to call get method to retrieve stats object?
EDIT
public class httpd implements Runnable
{
public static void main(String[] args)
{
httpd server = new httpd();
OtherClass oc = new OtherClass(server);
}
{
MY OWN MAIN
public class myownmain
{
public static void main(String[] args)
{
//Here I need OtherClass object created in httpd class
}
}
What's the problem in passing the passing the stats object to the other class you need inside a CTOR, by providing a getter to the stats object in class httpd -
this is only of course if the createHttpdStatistics method is not executed in the code of the run method (I suggest your pvovide it).
If the createHttpdStatistics method is executed within the run method (in a different thread) you should consider having a shared data structure between the threads (for example - shared Singletone that can be used as a shared data structure), if you want to create the HttpdStatistics object within a thread.
In this case the code will look like:
public class httpd implements Runnable
{
public void createHttpdStatistics()
{
httpdStatistics stats = new httpdStastics(this);
StatsManager.getInstance().putStats(stats);
}
public void run() {
//I assume the creation is done at the run method. Maybe I'm wrong here.
createHttpdStatistics();
}
}
And then use this somewhere in your code -
HttpdStatistics stats = StatsManager.getInstance().getStats();
MyClass stats = new MyClass(stats); //passing stats to another object.
You should of course make sure that getStats either blocks under the stats object is set to the singletone, or to check if getStats() returns null.
Given the code posted here:
In your other class, say OtherClass for example, you should have setter for httpd object or provide the httpd instance in the OtherClass constructor. This way OtherClass will have a reference to httpd
public class OtherClass{
httpd httpd_ = null;
public OtherClass(httpd httpd_){
this.httpd_ = httpd_;
}
// Access and use stats from httpd
public void useStats(){
httpdStatistics stats = httpd_.getStatistics()
if(stats != null){
// Do something here
}else{
// stats not set yet, the thread did probably not start yet
}
}
}
In your application's main you can have the following:
httpd h = new httpd();
OtherClass otherClass = new OtherClass(h);
EDIT As mentioned in one of the comments, the stats variable is shared among two threads so you will have to synchronize on it and make sure it is updated in a exclusive way.

Categories