Skip to content

Commit

Permalink
* Enhance Pointer.physicalBytes() by excluding shared pages from m…
Browse files Browse the repository at this point in the history
…emory-mapped files, etc (issue #468)
  • Loading branch information
saudet committed Jan 23, 2022
1 parent 8736a12 commit 2616b0b
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

* Enhance `Pointer.physicalBytes()` by excluding shared pages from memory-mapped files, etc ([issue #468](https://github.com/bytedeco/javacpp/issues/468))
* Fix `Parser` not correctly encoding files of top-level classes produced with `@Properties(target=..., global=...)`
* Add `Pointer.interruptDeallocatorThread()` method to make JavaCPP classes eligible for GC ([discussion bytedeco/javacpp-presets#1115](https://github.com/bytedeco/javacpp-presets/discussions/1115))
* Let `Parser` output the content of `Info.javaText` in the case of `FunctionPointer` as well
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/bytedeco/javacpp/Pointer.java
Original file line number Diff line number Diff line change
Expand Up @@ -572,8 +572,8 @@ public static long maxPhysicalBytes() {
/** Makes sure to return freed memory to the system, as required by Linux, at least. */
@Name("JavaCPP_trimMemory") private static native boolean trimMemory();

/** Returns the amount of physical memory currently used by the whole process, or 0 if unknown.
* Also known as "resident set size" (Linux, Mac OS X, etc) or "working set size" (Windows). */
/** Returns the amount of non-shared physical memory currently used by the whole process, or 0 if unknown.
* Also known as "anonymous resident set size" (Linux, Mac OS X, etc) or "private working set size" (Windows). */
@Name("JavaCPP_physicalBytes") public static native long physicalBytes();

/** Returns the amount of physical memory installed according to the operating system, or 0 if unknown.
Expand Down
35 changes: 26 additions & 9 deletions src/main/java/org/bytedeco/javacpp/tools/Generator.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2021 Samuel Audet
* Copyright (C) 2011-2022 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -552,21 +552,38 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver
out.println(" char* s;");
out.println(" int n;");
out.println(" if ((n = pread(fd, line, sizeof(line), 0)) > 0 && (s = (char*)memchr(line, ' ', n)) != NULL) {");
out.println(" size = (jlong)(atoll(s + 1) * getpagesize());");
out.println(" size = (jlong)atoll(s + 1);");
out.println(" if ((s = (char*)memchr(s + 1, ' ', n)) != NULL) {");
out.println(" size -= (jlong)atoll(s + 1);");
out.println(" }");
out.println(" }");
out.println(" size *= (jlong)getpagesize();");
out.println(" // no close(fd);");
out.println(" }");
out.println("#elif defined(__APPLE__)");
out.println(" task_basic_info info;");
out.println(" mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;");
out.println(" if (task_info(current_task(), TASK_BASIC_INFO, (task_info_t)&info, &count) == KERN_SUCCESS) {");
out.println(" size = (jlong)info.resident_size;");
out.println(" task_vm_info_data_t info;");
out.println(" mach_msg_type_number_t count = TASK_VM_INFO_COUNT;");
out.println(" if (task_info(current_task(), TASK_VM_INFO, (task_info_t)&info, &count) == KERN_SUCCESS) {");
out.println(" size = (jlong)info.internal;");
out.println(" }");
out.println("#elif defined(_WIN32)");
out.println(" PROCESS_MEMORY_COUNTERS counters;");
out.println(" if (GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters))) {");
out.println(" size = (jlong)counters.WorkingSetSize;");
out.println(" DWORD length = sizeof(PSAPI_WORKING_SET_INFORMATION);");
out.println(" PSAPI_WORKING_SET_INFORMATION *info = (PSAPI_WORKING_SET_INFORMATION*)malloc(length);");
out.println(" BOOL success = QueryWorkingSet(GetCurrentProcess(), info, length);");
out.println(" while (!success && GetLastError() == ERROR_BAD_LENGTH) {");
out.println(" length = sizeof(PSAPI_WORKING_SET_INFORMATION) + info->NumberOfEntries * sizeof(PSAPI_WORKING_SET_BLOCK);");
out.println(" info = (PSAPI_WORKING_SET_INFORMATION*)realloc(info, length);");
out.println(" success = QueryWorkingSet(GetCurrentProcess(), info, length);");
out.println(" }");
out.println(" if (success && info != NULL) {");
out.println(" for (DWORD i = 0; i < info->NumberOfEntries; i++) {");
out.println(" size += !info->WorkingSetInfo[i].Shared;");
out.println(" }");
out.println(" }");
out.println(" SYSTEM_INFO sysinfo;");
out.println(" GetSystemInfo(&sysinfo);");
out.println(" size *= (jlong)sysinfo.dwPageSize;");
out.println(" free(info);");
out.println("#endif");
out.println(" return size;");
out.println("}");
Expand Down
31 changes: 30 additions & 1 deletion src/test/java/org/bytedeco/javacpp/PointerTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2021 Samuel Audet
* Copyright (C) 2016-2022 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -29,7 +29,12 @@
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.MappedByteBuffer;
import java.nio.ShortBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -1145,4 +1150,28 @@ static class TestFunction extends FunctionPointer {
System.out.println(e);
}
}

@Test public void testNoFileBytes() throws Exception {
System.out.println("NoFileBytes");

System.gc();
Thread.sleep(100);
long bytesBefore = Pointer.physicalBytes();

Path file = Files.createTempFile("javacpp", "tmp");
FileChannel channel = FileChannel.open(file,
StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE,
StandardOpenOption.READ, StandardOpenOption.WRITE);
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 100_000_000);
for (int i = 0; i < 100_000_000; i++) {
buffer.put(i, (byte)i);
}

System.gc();
Thread.sleep(100);
long bytesAfter = Pointer.physicalBytes();

System.out.println(bytesBefore + " " + bytesAfter);
assertTrue(Math.abs(bytesAfter - bytesBefore) < 10_000_000 + buffer.get(0));
}
}

0 comments on commit 2616b0b

Please sign in to comment.