--
You received this message because you are subscribed to the Google Groups "memory-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to memory-dev+...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/memory-dev/CAN0uC_RNB%2BfnTHU0M5bdzRvNve-RhRbXjVedYKQW7Jt%2BcngU_g%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/memory-dev/CABg10jxXspOu5_%2B%2Bhw-3uNSSRoyAWsWSSqGuRAPhRrbZP37RMQ%40mail.gmail.com.
1. Run X.2. T = new time interval3. Schedule these steps to run when T sec passes.
// PartitionAlloc libraryclass TaskXClosure {public:void operator()();private:TaskXObject* task_x_object_;};using TaskXScheduler = void (*)(TaskXClosure, TimeDelta);TaskXScheduler g_scheduler;void StartTaskX(TaskXScheduler scheduler) {g_scheduler = scheduler;TaskXClosure task_x = create_task_X();TimeDelta t = calculate_new_interval();g_scheduler(task_x, t);}void TaskXClosure::operator()() {do_X();TimeDelta t = calculate_new_interval();g_scheduler(*this, t);}// Client code of PartitionAlloc library
// TaskRunner is available here.
void ScheduleTaskX(TaskXClosure task_x, TimeDelta t) {ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE,BindOnce([](TaskXClosure task_x) { task_x(); },task_x),t);}int main() {StartTaskX(ScheduleTaskX);}
Unfortunately, timer is implemented in //base. Plus, I vaguely remember that Chromium wants to have a (strong) control of event / task scheduling with their own prioritization. For example, Chromium may want to choose which task runner should be used for TaskX by themselves. I think it might not be desired that PartitionAlloc library implements its own timer and scheduling.
On Thu, Nov 25, 2021 at 11:34 AM Yuki Shiino <yukis...@chromium.org> wrote:Unfortunately, timer is implemented in //base. Plus, I vaguely remember that Chromium wants to have a (strong) control of event / task scheduling with their own prioritization. For example, Chromium may want to choose which task runner should be used for TaskX by themselves. I think it might not be desired that PartitionAlloc library implements its own timer and scheduling.Hm, but the whole premise here is "We're working to make PartitionAlloc library a standalone library (independent from //base library),"So there is no base?
2021年11月26日(金) 1:37 <dan...@chromium.org>:On Thu, Nov 25, 2021 at 11:34 AM Yuki Shiino <yukis...@chromium.org> wrote:Unfortunately, timer is implemented in //base. Plus, I vaguely remember that Chromium wants to have a (strong) control of event / task scheduling with their own prioritization. For example, Chromium may want to choose which task runner should be used for TaskX by themselves. I think it might not be desired that PartitionAlloc library implements its own timer and scheduling.Hm, but the whole premise here is "We're working to make PartitionAlloc library a standalone library (independent from //base library),"So there is no base?Right, there is no base. So, our idea is: PA library provides functions to be run periodically, and it's the application's responsibility to actually schedule tasks to run those functions.Timer and scheduler (task runner) must be implemented in applications. It's the application's responsibility to initialize the PA library and set up various things such as memory reclaimer, thread cache purger, and *scan. If the application never uses *scan, it's okay that the application doesn't set up a scheduler for *scan.Does this make sense?
The functions to be called back need some arguments. If we made all necessary arguments to global variables (global objects), then we don't need any argument, and just exposing functions works fine. This idea works well as long as memory reclaimer, thread cache registry, and *scan are singletons, but I'm afraid that it's fragile design and I'm not really sure if it's okay to assume these objects are singletons.If we don't like the way of global variables, a callback needs a pointer to a context object (= a bag of necessary arguments) at least. Thus, "a function pointer (callback) + a pointer to a context object" is another option on the table.I showed another idea using "non-generic closure".std::function is yet another option.I agree that "just a function + global variables" is an option, too.
class PublicMemoryReclaimer {...TimeDelta GetNextTimeInterval() const;bool ShouldRunMore() const;};
Looks great! However, we'd like some more features...- The PA library would like to control the time interval per each call (e.g. depending on how much memory is used/freed, the next scan can be delayed more (or less)).
- The PA library might want to stop it in case of unit tests. (In prod, it's unlikely that we need to stop memory reclaimer, etc.)
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/memory-dev/CAHtyhaSNYc3Nc21DFZ7ntbfFGq%2B9Lbd0%3DWfj-Aos6uYcb6xDgQ%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/memory-dev/CAA2pCLfWf0rvRwqkhou%2Bx7uFfW7avpHduhnaEn6k16U3e0_9NQ%40mail.gmail.com.
void ScheduleNextThreadCachePurge(delay) {
FROM_HERE,BindOnce(
[]() {TRACE_EVENT0("memory", "PeriodicPurge");auto new_delay = partition_alloc::PurgeThreadCache();ScheduleNextThreadCachePurge(new_delay)}),delay);}[...]ScheduleNextThreadCachePurge(partition_alloc::RecommendedInitialPurgeThreadCacheInterval());
auto delay = partition_alloc::RecommendedInitialPurgeThreadCacheInterval();while (1) {sleep(delay);delay = partition_alloc::PurgeThreadCache();}
I agree that the Platform pattern is very generic and have no objection to it. The Platform pattern is used between Blink and //content/ too.However, I like Bartek's idea for its simplicity -- it doesn't need to expose callbacks to the embedder. My personal preference is to 1) start with the simple API, 2) make PDFium, d8 and ARC++ work with PA, and 3) revise the API based on the learning. I'd prefer avoiding over-generalizing APIs before doing 2).
Thanks for a lot of input. I'm now very interested in the way of Platform object that V8 and Blink use (chrisha@'s idea).About C API, my impression is that the expected users of the PA library as of now are all C++ applications. I think it's okay for now to focus on C++ API. When any need of C API arises, we can build C API on top of C++ API.
Binary compatibility (ABI) is out of scope of the PA library, IIUC. Just like V8 and Blink, we won't provide any binary compatibility of the PA library. We provide only source code compatibility.
My point previously was that if you build the C API on top of the C++ API, then Chrome will not provide the coverage for this C API, so I'm expecting more issues with the other clients of the PA library. It is workable, just not ideal.
To make sure we are on the same page with what source code compatibility means, let me ask a question. If someone hypothetically wants to try the PA library with ARC, would they need to modify the source of the libc in ARC (bionic) and rebuild both the bionic and the PA library?
Thank you all for providing your thoughts and better ideas. It looks that everyone is happy with starting with a simple thing; it's the applications' responsibility to run periodic tasks. The PA library provides APIs to run periodic tasks, to get the next time interval, to get whether we should continue running the periodic tasks. We'll give it a shot to Dana + Bartek's idea.My point previously was that if you build the C API on top of the C++ API, then Chrome will not provide the coverage for this C API, so I'm expecting more issues with the other clients of the PA library. It is workable, just not ideal.The current implementation of the PartitionAlloc has already been written in C++. I guess that you're suggesting the following structure?C++ API --(use)--> C API --(use)--> C++ implementation of PArather thanC API --(use)--> C++ API --(use)--> C++ implementation of PAin order to exercise C API?If that's the only purpose, we can do it later I think. We can see whether we can build another C++ API on top of the proposed C API that is built on top of C++ API.C++ API for design evaluation --(use)--> C API --(use)--> C++ API --(use)--> C++ impl of PAPlus, I thought that we wouldn't want very different C API from C++ API. I was thinking of something like below, almost 1:1 mappings.// C++ APIclass File {static File* Open(...);bool Read(...);};// C APIFilePtr FileOpen(...) { return File::Open(...); }bool FileRead(FilePtr fp, ...) { return ((File*)fp)->Read(...); }// where the first argument `fp` is essentially `this` pointer.This should be quite similar to what fopen(3C), fread(3C), etc. look like. I was optimistic about C API design given that we could design C++ API elegantly; C API should naturally be elegant due to the elegantness of C++ API.
To make sure we are on the same page with what source code compatibility means, let me ask a question. If someone hypothetically wants to try the PA library with ARC, would they need to modify the source of the libc in ARC (bionic) and rebuild both the bionic and the PA library?No, no need to modify the source of libc. Both PA and PA-E (PartitionAlloc-Everywhere aka PartitionAlloc as malloc) have been shipped on Chrome for Android, but we've not modified libc source.
When I wrote "no binary compatibility", I meant "binary compatibility to applications", i.e. ABI between the PA library and its application code, not ABI between the PA library and libc nor libc++.
On Tue, Nov 30, 2021 at 6:24 PM Yuki Shiino <yukis...@chromium.org> wrote:Thank you all for providing your thoughts and better ideas. It looks that everyone is happy with starting with a simple thing; it's the applications' responsibility to run periodic tasks. The PA library provides APIs to run periodic tasks, to get the next time interval, to get whether we should continue running the periodic tasks. We'll give it a shot to Dana + Bartek's idea.My point previously was that if you build the C API on top of the C++ API, then Chrome will not provide the coverage for this C API, so I'm expecting more issues with the other clients of the PA library. It is workable, just not ideal.The current implementation of the PartitionAlloc has already been written in C++. I guess that you're suggesting the following structure?C++ API --(use)--> C API --(use)--> C++ implementation of PArather thanC API --(use)--> C++ API --(use)--> C++ implementation of PAin order to exercise C API?If that's the only purpose, we can do it later I think. We can see whether we can build another C++ API on top of the proposed C API that is built on top of C++ API.C++ API for design evaluation --(use)--> C API --(use)--> C++ API --(use)--> C++ impl of PAPlus, I thought that we wouldn't want very different C API from C++ API. I was thinking of something like below, almost 1:1 mappings.// C++ APIclass File {static File* Open(...);bool Read(...);};// C APIFilePtr FileOpen(...) { return File::Open(...); }bool FileRead(FilePtr fp, ...) { return ((File*)fp)->Read(...); }// where the first argument `fp` is essentially `this` pointer.This should be quite similar to what fopen(3C), fread(3C), etc. look like. I was optimistic about C API design given that we could design C++ API elegantly; C API should naturally be elegant due to the elegantness of C++ API.Now I am confused. I thought PA as a library would expose malloc/calloc/free/memalign etc. along with extended API for more fine control of purging, thread cache sizing etc. Is the API with FilePtr above an example/inspiration? I don't see how it fits the goals, sorry :)
To make sure we are on the same page with what source code compatibility means, let me ask a question. If someone hypothetically wants to try the PA library with ARC, would they need to modify the source of the libc in ARC (bionic) and rebuild both the bionic and the PA library?No, no need to modify the source of libc. Both PA and PA-E (PartitionAlloc-Everywhere aka PartitionAlloc as malloc) have been shipped on Chrome for Android, but we've not modified libc source.Without modifying the sources of the libc, how would Android apps in ARC, like PlayStore, be switched to use PA? If I understand correctly, ARC runs inside Chrome, but Chrome does not run inside ARC :)
When I wrote "no binary compatibility", I meant "binary compatibility to applications", i.e. ABI between the PA library and its application code, not ABI between the PA library and libc nor libc++.This would mean every app using libc for allocating memory will need to be modified to use PA and be re-linked with it? If we throw C++ across the board, we'd need to be careful of what we use: because the app code could rely on a different libc++ version than PA. If there aren't too many apps to relink like that, then we can surely solve this case by case.
To make sure we are on the same page with what source code compatibility means, let me ask a question. If someone hypothetically wants to try the PA library with ARC, would they need to modify the source of the libc in ARC (bionic) and rebuild both the bionic and the PA library?No, no need to modify the source of libc. Both PA and PA-E (PartitionAlloc-Everywhere aka PartitionAlloc as malloc) have been shipped on Chrome for Android, but we've not modified libc source.Without modifying the sources of the libc, how would Android apps in ARC, like PlayStore, be switched to use PA? If I understand correctly, ARC runs inside Chrome, but Chrome does not run inside ARC :)We suppose two cases: explicit use of PartitionAlloc and PartitionAlloc-Everywhere.[Explicit use of PartitionAlloc]You instantiate PartitionRoot and call PartitionRoot::Alloc(size, type_name), for example, in order to allocate a memory region. You're expected to use PartitionAlloc APIs explicitly instead of malloc/free or operator new/delete.[PartitionAlloc-Everywhere]This is a way to make malloc/free/etc. backed by PartitionAlloc, so you don't need to explicitly use PartitionAlloc APIs (except for the initial setup). The way how to intercept the system default malloc/free/etc. highly depends on platforms. On Linux, we hijack the exported symbols of `malloc`, `free`, etc. On Android, the apps are expected to use `-Wl,--wrap=malloc`, etc. On Android P and later, there is a better way but we've not yet supported it. On macOS, we hijack the system default malloc zone.
When I wrote "no binary compatibility", I meant "binary compatibility to applications", i.e. ABI between the PA library and its application code, not ABI between the PA library and libc nor libc++.This would mean every app using libc for allocating memory will need to be modified to use PA and be re-linked with it? If we throw C++ across the board, we'd need to be careful of what we use: because the app code could rely on a different libc++ version than PA. If there aren't too many apps to relink like that, then we can surely solve this case by case.Yes, every app is expected to be modified to use PA (at least the initialization of PA-E) and re-linked with the PA library.
Overall, we expect that the PA library will look similar to tcmalloc, jemalloc, and mimalloc (not exactly the same, but also not very different). The applications' source code needs slight modifications and the apps need to be linked with the library.
Thank you for the detailed explanation of the goals. It all makes sense. I feel sorry now for having sent so many inquiries.Some more thoughts below.On Thu, Dec 2, 2021 at 9:05 AM Yuki Shiino <yukis...@chromium.org> wrote:To make sure we are on the same page with what source code compatibility means, let me ask a question. If someone hypothetically wants to try the PA library with ARC, would they need to modify the source of the libc in ARC (bionic) and rebuild both the bionic and the PA library?No, no need to modify the source of libc. Both PA and PA-E (PartitionAlloc-Everywhere aka PartitionAlloc as malloc) have been shipped on Chrome for Android, but we've not modified libc source.Without modifying the sources of the libc, how would Android apps in ARC, like PlayStore, be switched to use PA? If I understand correctly, ARC runs inside Chrome, but Chrome does not run inside ARC :)We suppose two cases: explicit use of PartitionAlloc and PartitionAlloc-Everywhere.[Explicit use of PartitionAlloc]You instantiate PartitionRoot and call PartitionRoot::Alloc(size, type_name), for example, in order to allocate a memory region. You're expected to use PartitionAlloc APIs explicitly instead of malloc/free or operator new/delete.[PartitionAlloc-Everywhere]This is a way to make malloc/free/etc. backed by PartitionAlloc, so you don't need to explicitly use PartitionAlloc APIs (except for the initial setup). The way how to intercept the system default malloc/free/etc. highly depends on platforms. On Linux, we hijack the exported symbols of `malloc`, `free`, etc. On Android, the apps are expected to use `-Wl,--wrap=malloc`, etc. On Android P and later, there is a better way but we've not yet supported it. On macOS, we hijack the system default malloc zone.On Android (such as ARC) injecting PA-E early in the system zygote should easily enable experiments and perhaps even deploy systemwide, without the apps even knowing which allocator they use (unless an app overrides with jemalloc/etc explicitly - that should be rare) and observe the magnitude of memory savings. There are several ways to do it, and having traditional C APIs would simplify it. An additional problem of asking every app to link against PA-E explicitly is that we will end up with many copies of PA on the system - consuming disk and RAM. All in all, a scalable solution is not at all obvious (for Android and ARC). Worth another discussion?
Android (OS) team should be interested in using the PartitionAlloc library as the system default allocator. In that case, no changes for Android apps are required because malloc and operator new will be backed by PA by default on Android. malloc() will be implemented using PartitionRoot::Alloc in that case.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/memory-dev/CAN0uC_QWU5FtXhcwjK2Cqg%2BFQUdjx2ZYrczNZXf7O3kgOnnamQ%40mail.gmail.com.