I'm using DL4J in my Android project to run a CNN network as classifier. The problem is that this CNN model occupies more memories than the allowed per application heap size of my smartphone, which leads to out of memory error. So, I'm wondering if there is a way to explicitly free the memories that this native DL4J code allocates.
My inputs are 200 image patches in total. I need to stack them together so the processing time is faster. I tried to set the batch size to 32 so each input INDARRAY is size [32, 3, 44, 44]. I also tried 16, 8, etc.. But the only time that I don't get out of memory error is when I input the image patch one at a time. But I can't afford to have the long processing time that it leads to.
I tried to free the memory explicitly with GC, but it didn't work, which makes sense because the memory were taken by native code.
for (int i = 0; i < N / UtilsCustom.NN_batch_size; i++) {
INDArray temp = UtilsCustom.overallArray.get(NDArrayIndex.interval(i * UtilsCustom.NN_batch_size, i * UtilsCustom.NN_batch_size + UtilsCustom.NN_batch_size), NDArrayIndex.all(), NDArrayIndex.all(), NDArrayIndex.all());
NN_classify(temp);
a = i * UtilsCustom.NN_batch_size + UtilsCustom.NN_batch_size;
if (i%2==1){
model = null;
java.lang.System.gc();
Log.d(TAG, "GCGCGC");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
loadNNModel();
}
temp = null;
java.lang.System.gc();
}
private void NN_classify(INDArray imageMat) {
int result;
DataNormalization scaler = new ImagePreProcessingScaler(0, 1);
scaler.transform(imageMat);
INDArray output = model.output(imageMat);
Log.d(LOG_TAG, "output.size(): " + output.size(0) + ", " + output.size(1));
double prob_parasitemic = 0, prob_uninfected = 0;
for (int i = 0; i < output.size(0); i++) {
prob_parasitemic = output.getDouble(i, 0);
prob_uninfected = output.getDouble(i, 1);
Log.d(LOG_TAG, "prob_parasitemic: " + i + " " + output.getDouble(0, 0));
Log.d(LOG_TAG, "prob_uninfected: " + i + " " + output.getDouble(0, 1));
}
if (prob_parasitemic > prob_uninfected) {
result = 2;
} else {
result = 1;
}
Log.e(LOG_TAG, "Result: " + result);
imageMat = null;
output = null;
java.lang.System.gc();
}
java.lang.System.gc() does not do what you think it does. It is not like free in C or delete in C++.
It is more of a "suggestion" to the JVM to run garbage collection. It does not force garbage collection or freeing of memory.
Reference this: https://stackoverflow.com/a/66573/9241296
It states,
I wouldn't depend on it in your code. If the JVM is about to throw an OutOfMemoryError, calling System.gc() won't stop it, because the garbage collector will attempt to free as much as it can before it goes to that extreme.
So I'm currently trying to increase the download speed of an application, to do so I tried to implement segmented downloading.
The code works like a charm, but in 5 test cases, 2 times the resulting File wasn't able to be opened or looked strange.
import java.nio.ByteBuffer
import java.nio.channels.ClosedChannelException
import java.nio.channels.FileChannel
//https://www.fareway.com/stores/ia/cresco/112-south-elm-street/ad/weekly/download
class Playground {
final int SEGMENT_SIZE = 8192 * 8
final int THREAD_COUNT = 8
final int UPDATE_INTERVAL = 2
boolean running = false
int target_size
static void main(String[] args){
new Playground()
}
Playground(){
running = true
long time_started_execution = System.currentTimeMillis()
URL testurl = new URL("https://www.fareway.com/stores/ia/cresco/112-south-elm-street/ad/weekly/download")
target_size = testurl.openConnection().getContentLength()
URL url = new URL("https://www.fareway.com/stores/ia/cresco/112-south-elm-street/ad/weekly/download")
File outFile = new File("testfile.pdf")
if(outFile.exists()) outFile.delete()
RandomAccessFile raf = new RandomAccessFile(outFile, "rw")
FileChannel channel = raf.getChannel()
def thread_list = []
THREAD_COUNT.times { int n ->
def t = Thread.start {
int pos = n * SEGMENT_SIZE
while(downloadSegment(url, pos, channel)){
pos+=THREAD_COUNT*SEGMENT_SIZE
}
}
t.setName("Download Thread T$n")
thread_list << t
}
def monitor_thread = Thread.start{
while(running){
try{
int before = channel.size()
sleep(UPDATE_INTERVAL * 1000)
double speed = (channel.size() - before) / UPDATE_INTERVAL
print("\rDownloading with ${speed / 1024} kb/s. (${channel.size() / 1024} / ${(target_size / 1024) as int} kb)")
}catch (ClosedChannelException cce){
running = false
}
}
}
thread_list.each{
it.join()
}
running = false
println("\n(${channel.size()} / ${(target_size)} bytes)")
raf.close()
println("Download finished in ${(System.currentTimeMillis() - time_started_execution) / 1000} s!")
}
boolean downloadSegment(URL url, int position, FileChannel channel){
if(position > target_size){
return false
}
int endPos = position+SEGMENT_SIZE-1
if(endPos > target_size){
endPos = target_size
}
HttpURLConnection conn = url.openConnection() as HttpURLConnection
conn.setRequestProperty("Range", "bytes=$position-$endPos")
//println("${Thread.currentThread().getName()}: bytes=$position-${position+SEGMENT_SIZE-1}")
conn.connect()
int current_segment_size = conn.getContentLength()
if(conn.getResponseCode() != 200 && conn.getResponseCode() != 206){
//println("\n${Thread.currentThread().getName()}: No more data!")
return false
}
byte[] buffer = conn.getInputStream().getBytes()
ByteBuffer bf = ByteBuffer.wrap(buffer)
//Set Channel Position to write at the correct place.
channel.position(position)
while(bf.hasRemaining()){
channel.write(bf)
channel.force(false)
}
bf.clear()
return current_segment_size >= SEGMENT_SIZE
}
}
So does anyone have a clue what I can try to avoid corrupted files ?
I did try to lower Thread_Count and also Segment_Size, if they are lower, the file is less likely to be corrupted, but it also lowers the download speed from around 1.5 Mb/s to 400 kb/s ... And I want to get the maximum speed here.
Thanks in advance for any help.
P.S.: I know that there are missing try-catch or other things. But this was just a Groovy Playground, to test this feature in a safe environment.
I'm building a sort of custom version of wireshark with jnetpcap v1.4r1425. I just want to open offline pcap files and display them in my tableview, which works great except for the speed.
The files I open are around 100mb with 700k packages.
public ObservableList<Frame> readOfflineFiles1(int numFrames) {
ObservableList<Frame> frameData = FXCollections.observableArrayList();
if (numFrames == 0){
numFrames = Pcap.LOOP_INFINITE;
}
final StringBuilder errbuf = new StringBuilder();
final Pcap pcap = Pcap.openOffline(FileAddress, errbuf);
if (pcap == null) {
System.err.println(errbuf); // Error is stored in errbuf if any
return null;
}
JPacketHandler<StringBuilder> packetHandler = new JPacketHandler<StringBuilder>() {
public void nextPacket(JPacket packet, StringBuilder errbuf) {
if (packet.hasHeader(ip)){
sourceIpRaw = ip.source();
destinationIpRaw = ip.destination();
sourceIp = org.jnetpcap.packet.format.FormatUtils.ip(sourceIpRaw);
destinationIp = org.jnetpcap.packet.format.FormatUtils.ip(destinationIpRaw);
}
if (packet.hasHeader(tcp)){
protocol = tcp.getName();
length = tcp.size();
int payloadOffset = tcp.getOffset() + tcp.size();
int payloadLength = tcp.getPayloadLength();
buffer.peer(packet, payloadOffset, payloadLength); // No copies, by native reference
info = buffer.toHexdump();
} else if (packet.hasHeader(udp)){
protocol = udp.getName();
length = udp.size();
int payloadOffset = udp.getOffset() + udp.size();
int payloadLength = udp.getPayloadLength();
buffer.peer(packet, payloadOffset, payloadLength); // No copies, by native reference
info = buffer.toHexdump();
}
if (packet.hasHeader(payload)){
infoRaw = payload.getPayload();
length = payload.size();
}
frameData.add(new Frame(packet.getCaptureHeader().timestampInMillis(), sourceIp, destinationIp, protocol, length, info ));
//System.out.print(i+"\n");
//i=i+1;
}
};
pcap.loop(numFrames, packetHandler , errbuf);
pcap.close();
return frameData;
}
This code is very fast for the first maybe 400k packages, but after that it slows down a lot. It needs around 1 minute for the first 400k packages and around 10 minutes for the rest. What is the issue here?
It's not that the list is getting too timeconsuming to work with is it? the listmethod add is O(1), isnt it?
I asked about this on the official jnetpcap forums too but it's not very active.
edit:
turn out it slows down massively because of the heap usage. Is there a way to reduce this?
As the profiler showed you, you're running low on memory and it starts to slow down.
Either give more memory with -Xmx or don't load all the packets into memory at once.
I am new in Android and I want to find free memory in internal storage. I use two function to find free memory but they show me two different values in long format. I don't know why?
Here is my code:
1) Result of getTIM() function is 558628864
public String getTIM(){
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
String str = Long.toString(blockSize * totalBlocks);
return str;
}
2) Result of ITMStr() function is 914120704
public String ITMStr(){
StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath());
long blockCount = statFs.getBlockCountLong();
long blockSize = statFs.getBlockSizeLong();
long total = blockCount * blockSize;
String str = Long.toString(total);
return str;
}
Which value is right?
According to reference:
public static File getDataDirectory ()
Added in API level 1 Return the user data directory.
_
public static File getRootDirectory ()
Added in API level 1 Return root of the "system" partition holding the
core Android OS. Always present and mounted read-only.
So sizes are different as you are getting sizes for different stuff.
I would like to monitor the following system information in Java:
Current CPU usage** (percent)
Available memory* (free/total)
Available disk space (free/total)
*Note that I mean overall memory available to the whole system, not just the JVM.
I'm looking for a cross-platform solution (Linux, Mac, and Windows) that doesn't rely on my own code calling external programs or using JNI. Although these are viable options, I would prefer not to maintain OS-specific code myself if someone already has a better solution.
If there's a free library out there that does this in a reliable, cross-platform manner, that would be great (even if it makes external calls or uses native code itself).
Any suggestions are much appreciated.
To clarify, I would like to get the current CPU usage for the whole system, not just the Java process(es).
The SIGAR API provides all the functionality I'm looking for in one package, so it's the best answer to my question so far. However, due it being licensed under the GPL, I cannot use it for my original purpose (a closed source, commercial product). It's possible that Hyperic may license SIGAR for commercial use, but I haven't looked into it. For my GPL projects, I will definitely consider SIGAR in the future.
For my current needs, I'm leaning towards the following:
For CPU usage, OperatingSystemMXBean.getSystemLoadAverage() / OperatingSystemMXBean.getAvailableProcessors() (load average per cpu)
For memory, OperatingSystemMXBean.getTotalPhysicalMemorySize() and OperatingSystemMXBean.getFreePhysicalMemorySize()
For disk space, File.getTotalSpace() and File.getUsableSpace()
Limitations:
The getSystemLoadAverage() and disk space querying methods are only available under Java 6. Also, some JMX functionality may not be available to all platforms (i.e. it's been reported that getSystemLoadAverage() returns -1 on Windows).
Although originally licensed under GPL, it has been changed to Apache 2.0, which can generally be used for closed source, commercial products.
Along the lines of what I mentioned in this post. I recommend you use the SIGAR API. I use the SIGAR API in one of my own applications and it is great. You'll find it is stable, well supported, and full of useful examples. It is open-source with a GPL 2 Apache 2.0 license. Check it out. I have a feeling it will meet your needs.
Using Java and the Sigar API you can get Memory, CPU, Disk, Load-Average, Network Interface info and metrics, Process Table information, Route info, etc.
The following supposedly gets you CPU and RAM. See ManagementFactory for more details.
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
private static void printUsage() {
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
for (Method method : operatingSystemMXBean.getClass().getDeclaredMethods()) {
method.setAccessible(true);
if (method.getName().startsWith("get")
&& Modifier.isPublic(method.getModifiers())) {
Object value;
try {
value = method.invoke(operatingSystemMXBean);
} catch (Exception e) {
value = e;
} // try
System.out.println(method.getName() + " = " + value);
} // if
} // for
}
In JDK 1.7, you can get system CPU and memory usage via com.sun.management.OperatingSystemMXBean. This is different than java.lang.management.OperatingSystemMXBean.
long getCommittedVirtualMemorySize()
// Returns the amount of virtual memory that is guaranteed to be available to the running process in bytes, or -1 if this operation is not supported.
long getFreePhysicalMemorySize()
// Returns the amount of free physical memory in bytes.
long getFreeSwapSpaceSize()
// Returns the amount of free swap space in bytes.
double getProcessCpuLoad()
// Returns the "recent cpu usage" for the Java Virtual Machine process.
long getProcessCpuTime()
// Returns the CPU time used by the process on which the Java virtual machine is running in nanoseconds.
double getSystemCpuLoad()
// Returns the "recent cpu usage" for the whole system.
long getTotalPhysicalMemorySize()
// Returns the total amount of physical memory in bytes.
long getTotalSwapSpaceSize()
// Returns the total amount of swap space in bytes.
This works for me perfectly without any external API, just native Java hidden feature :)
import com.sun.management.OperatingSystemMXBean;
...
OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
OperatingSystemMXBean.class);
// What % CPU load this current JVM is taking, from 0.0-1.0
System.out.println(osBean.getProcessCpuLoad());
// What % load the overall system is at, from 0.0-1.0
System.out.println(osBean.getSystemCpuLoad());
Have a look at this very detailled article:
http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking#UsingaSuninternalclasstogetJVMCPUtime
To get the percentage of CPU used, all you need is some simple maths:
MBeanServerConnection mbsc = ManagementFactory.getPlatformMBeanServer();
OperatingSystemMXBean osMBean = ManagementFactory.newPlatformMXBeanProxy(
mbsc, ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);
long nanoBefore = System.nanoTime();
long cpuBefore = osMBean.getProcessCpuTime();
// Call an expensive task, or sleep if you are monitoring a remote process
long cpuAfter = osMBean.getProcessCpuTime();
long nanoAfter = System.nanoTime();
long percent;
if (nanoAfter > nanoBefore)
percent = ((cpuAfter-cpuBefore)*100L)/
(nanoAfter-nanoBefore);
else percent = 0;
System.out.println("Cpu usage: "+percent+"%");
Note: You must import com.sun.management.OperatingSystemMXBean and not java.lang.management.OperatingSystemMXBean.
The accepted answer in 2008 recommended SIGAR. However, as a comment from 2014 (#Alvaro) says:
Be careful when using Sigar, there are problems on x64 machines...
Sigar 1.6.4 is crashing: EXCEPTION_ACCESS_VIOLATION and it seems the library
doesn't get updated since 2010
My recommendation is to use https://github.com/oshi/oshi
Or the answer mentioned above.
For disk space, if you have Java 6, you can use the getTotalSpace and getFreeSpace methods on File. If you're not on Java 6, I believe you can use Apache Commons IO to get some of the way there.
I don't know of any cross platform way to get CPU usage or Memory usage I'm afraid.
A lot of this is already available via JMX. With Java 5, JMX is built-in and they include a JMX console viewer with the JDK.
You can use JMX to monitor manually, or invoke JMX commands from Java if you need this information in your own run-time.
/* YOU CAN TRY THIS TOO */
import java.io.File;
import java.lang.management.ManagementFactory;
// import java.lang.management.OperatingSystemMXBean;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.management.RuntimeMXBean;
import java.io.*;
import java.net.*;
import java.util.*;
import java.io.LineNumberReader;
import java.lang.management.ManagementFactory;
import com.sun.management.OperatingSystemMXBean;
import java.lang.management.ManagementFactory;
import java.util.Random;
public class Pragati
{
public static void printUsage(Runtime runtime)
{
long total, free, used;
int mb = 1024*1024;
total = runtime.totalMemory();
free = runtime.freeMemory();
used = total - free;
System.out.println("\nTotal Memory: " + total / mb + "MB");
System.out.println(" Memory Used: " + used / mb + "MB");
System.out.println(" Memory Free: " + free / mb + "MB");
System.out.println("Percent Used: " + ((double)used/(double)total)*100 + "%");
System.out.println("Percent Free: " + ((double)free/(double)total)*100 + "%");
}
public static void log(Object message)
{
System.out.println(message);
}
public static int calcCPU(long cpuStartTime, long elapsedStartTime, int cpuCount)
{
long end = System.nanoTime();
long totalAvailCPUTime = cpuCount * (end-elapsedStartTime);
long totalUsedCPUTime = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime()-cpuStartTime;
//log("Total CPU Time:" + totalUsedCPUTime + " ns.");
//log("Total Avail CPU Time:" + totalAvailCPUTime + " ns.");
float per = ((float)totalUsedCPUTime*100)/(float)totalAvailCPUTime;
log( per);
return (int)per;
}
static boolean isPrime(int n)
{
// 2 is the smallest prime
if (n <= 2)
{
return n == 2;
}
// even numbers other than 2 are not prime
if (n % 2 == 0)
{
return false;
}
// check odd divisors from 3
// to the square root of n
for (int i = 3, end = (int)Math.sqrt(n); i <= end; i += 2)
{
if (n % i == 0)
{
return false;
}
}
return true;
}
public static void main(String [] args)
{
int mb = 1024*1024;
int gb = 1024*1024*1024;
/* PHYSICAL MEMORY USAGE */
System.out.println("\n**** Sizes in Mega Bytes ****\n");
com.sun.management.OperatingSystemMXBean operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
//RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
//operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean)
java.lang.management.ManagementFactory.getOperatingSystemMXBean();
long physicalMemorySize = os.getTotalPhysicalMemorySize();
System.out.println("PHYSICAL MEMORY DETAILS \n");
System.out.println("total physical memory : " + physicalMemorySize / mb + "MB ");
long physicalfreeMemorySize = os.getFreePhysicalMemorySize();
System.out.println("total free physical memory : " + physicalfreeMemorySize / mb + "MB");
/* DISC SPACE DETAILS */
File diskPartition = new File("C:");
File diskPartition1 = new File("D:");
File diskPartition2 = new File("E:");
long totalCapacity = diskPartition.getTotalSpace() / gb;
long totalCapacity1 = diskPartition1.getTotalSpace() / gb;
double freePartitionSpace = diskPartition.getFreeSpace() / gb;
double freePartitionSpace1 = diskPartition1.getFreeSpace() / gb;
double freePartitionSpace2 = diskPartition2.getFreeSpace() / gb;
double usablePatitionSpace = diskPartition.getUsableSpace() / gb;
System.out.println("\n**** Sizes in Giga Bytes ****\n");
System.out.println("DISC SPACE DETAILS \n");
//System.out.println("Total C partition size : " + totalCapacity + "GB");
//System.out.println("Usable Space : " + usablePatitionSpace + "GB");
System.out.println("Free Space in drive C: : " + freePartitionSpace + "GB");
System.out.println("Free Space in drive D: : " + freePartitionSpace1 + "GB");
System.out.println("Free Space in drive E: " + freePartitionSpace2 + "GB");
if(freePartitionSpace <= totalCapacity%10 || freePartitionSpace1 <= totalCapacity1%10)
{
System.out.println(" !!!alert!!!!");
}
else
System.out.println("no alert");
Runtime runtime;
byte[] bytes;
System.out.println("\n \n**MEMORY DETAILS ** \n");
// Print initial memory usage.
runtime = Runtime.getRuntime();
printUsage(runtime);
// Allocate a 1 Megabyte and print memory usage
bytes = new byte[1024*1024];
printUsage(runtime);
bytes = null;
// Invoke garbage collector to reclaim the allocated memory.
runtime.gc();
// Wait 5 seconds to give garbage collector a chance to run
try {
Thread.sleep(5000);
} catch(InterruptedException e) {
e.printStackTrace();
return;
}
// Total memory will probably be the same as the second printUsage call,
// but the free memory should be about 1 Megabyte larger if garbage
// collection kicked in.
printUsage(runtime);
for(int i = 0; i < 30; i++)
{
long start = System.nanoTime();
// log(start);
//number of available processors;
int cpuCount = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
Random random = new Random(start);
int seed = Math.abs(random.nextInt());
log("\n \n CPU USAGE DETAILS \n\n");
log("Starting Test with " + cpuCount + " CPUs and random number:" + seed);
int primes = 10000;
//
long startCPUTime = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();
start = System.nanoTime();
while(primes != 0)
{
if(isPrime(seed))
{
primes--;
}
seed++;
}
float cpuPercent = calcCPU(startCPUTime, start, cpuCount);
log("CPU USAGE : " + cpuPercent + " % ");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e) {}
}
try
{
Thread.sleep(500);
}`enter code here`
catch (Exception ignored) { }
}
}
The following code is Linux (maybe Unix) only, but it works in a real project.
private double getAverageValueByLinux() throws InterruptedException {
try {
long delay = 50;
List<Double> listValues = new ArrayList<Double>();
for (int i = 0; i < 100; i++) {
long cput1 = getCpuT();
Thread.sleep(delay);
long cput2 = getCpuT();
double cpuproc = (1000d * (cput2 - cput1)) / (double) delay;
listValues.add(cpuproc);
}
listValues.remove(0);
listValues.remove(listValues.size() - 1);
double sum = 0.0;
for (Double double1 : listValues) {
sum += double1;
}
return sum / listValues.size();
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
private long getCpuT throws FileNotFoundException, IOException {
BufferedReader reader = new BufferedReader(new FileReader("/proc/stat"));
String line = reader.readLine();
Pattern pattern = Pattern.compile("\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)")
Matcher m = pattern.matcher(line);
long cpuUser = 0;
long cpuSystem = 0;
if (m.find()) {
cpuUser = Long.parseLong(m.group(1));
cpuSystem = Long.parseLong(m.group(3));
}
return cpuUser + cpuSystem;
}
Make a batch file "Pc.bat" as,
typeperf -sc 1 "\mukit\processor(_Total)\%% Processor Time"
You can use the class MProcess,
/*
*Md. Mukit Hasan
*CSE-JU,35
**/
import java.io.*;
public class MProcessor {
public MProcessor() {
String s;
try {
Process ps = Runtime.getRuntime().exec("Pc.bat");
BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
while((s = br.readLine()) != null) {
System.out.println(s);
}
}
catch( Exception ex ) {
System.out.println(ex.toString());
}
}
}
Then after some string manipulation, you get the CPU use. You can use the same process for other tasks.
--Mukit Hasan
OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
System.out.println((osBean.getCpuLoad() * 100) + "%");
import com.sun.management.OperatingSystemMXBean
It only starts working after the second call so save the osBean and put it in a loop