--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAJTZ7LJiDrU4i6vyfeK35wf18ntXOXO_b-RXUxKfzZfnAKRF%3Dw%40mail.gmail.com.
I've got a review for some bits of DB thread migration and I realized that I do not know enough about the DB thread to make the right call.We can make a sequence per sqlite DB, this would be pretty straightforward. Is it the current recommendation? While this helps with code health and potential metrics, I don't think it would open any new scheduling opportunities.The pattern I saw in a few places is:1. read all contents of the DB into RAM on initialization2. on updates of this working set, throw a task to DB thread to flush the delta to disk3. (optionally) throttle somewhat to reduce amount of flushes (powering up disks, etc), but still provide some persistency guarantees (which are specific to particular sqlite DB)4. the DB thread is mostly idle most of the time, and blocks nothing user-visibleDo you think this needs more advanced scheduling other than one thread for all the sqlite DBs? Do we expect the new metrics to show opportunities here?
Can we do this without measuring? One particular dragon I am seeing: parallelizing the tasks on the DB thread may have undesired consequences of having more parallel disk I/O (example: spinny disks under heavy seek storms that would block critical reads from the filesystem, such as HTTP disk cache, similar story for cheap eMMC on Android), does the scheduler API have any primitives to address this potential concern?
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAJTZ7LJiDrU4i6vyfeK35wf18ntXOXO_b-RXUxKfzZfnAKRF%3Dw%40mail.gmail.com.
--Egor Pasko
On Wed, Jun 14, 2017 at 2:16 PM Egor Pasko <pa...@google.com> wrote:I've got a review for some bits of DB thread migration and I realized that I do not know enough about the DB thread to make the right call.We can make a sequence per sqlite DB, this would be pretty straightforward. Is it the current recommendation? While this helps with code health and potential metrics, I don't think it would open any new scheduling opportunities.The pattern I saw in a few places is:1. read all contents of the DB into RAM on initialization2. on updates of this working set, throw a task to DB thread to flush the delta to disk3. (optionally) throttle somewhat to reduce amount of flushes (powering up disks, etc), but still provide some persistency guarantees (which are specific to particular sqlite DB)4. the DB thread is mostly idle most of the time, and blocks nothing user-visibleDo you think this needs more advanced scheduling other than one thread for all the sqlite DBs? Do we expect the new metrics to show opportunities here?If there isn't much contention on that thread already then I think it's fine moving it all to the same SequencedTaskRunner.
What matters is that it's provided by post_task.h so that 1) we use a common API everywhere and 2) tasks go through TaskTracker which is where all modern instrumentation/profiling is being added.Ref. lazy_task_runner.h for an API that allows you to have one TaskRunner accessible statically for all your tasks. Having dedicated objects for each logically associated set of tasks is cleaner (even when ignoring scheduling) -- e.g. this is like when we went from global notifications -> ObserverLists.
Can we do this without measuring? One particular dragon I am seeing: parallelizing the tasks on the DB thread may have undesired consequences of having more parallel disk I/O (example: spinny disks under heavy seek storms that would block critical reads from the filesystem, such as HTTP disk cache, similar story for cheap eMMC on Android), does the scheduler API have any primitives to address this potential concern?Yes, that's actually another argument for bringing these tasks explicitly to the TaskScheduler. Once the TaskScheduler is aware of all the work, everything is possible.
It can dynamically adjust to the current machine's resources (disk, CPU, etc.). Just because things are split on different sequences and *could* run in parallel doesn't mean they actually will, that's the scheduler's decision and it can make a better decision here if there aren't other threads running wild doing their own thing.In practice, TaskScheduler v1 has as many worker threads available for I/O as BlockingPool + CachePool combined previously did, aiming to maintain the status quo initially (or slightly improve it as task priority still has a chance to help in some scenarios), this is nowhere near optimized though -- we will run experiments once we have a full workload, getting to a full workload without regressions is the current goal.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAJTZ7LJiDrU4i6vyfeK35wf18ntXOXO_b-RXUxKfzZfnAKRF%3Dw%40mail.gmail.com.
--Egor Pasko
On Wed, Jun 14, 2017 at 8:30 PM, Gabriel Charette <g...@chromium.org> wrote:On Wed, Jun 14, 2017 at 2:16 PM Egor Pasko <pa...@google.com> wrote:I've got a review for some bits of DB thread migration and I realized that I do not know enough about the DB thread to make the right call.We can make a sequence per sqlite DB, this would be pretty straightforward. Is it the current recommendation? While this helps with code health and potential metrics, I don't think it would open any new scheduling opportunities.The pattern I saw in a few places is:1. read all contents of the DB into RAM on initialization2. on updates of this working set, throw a task to DB thread to flush the delta to disk3. (optionally) throttle somewhat to reduce amount of flushes (powering up disks, etc), but still provide some persistency guarantees (which are specific to particular sqlite DB)4. the DB thread is mostly idle most of the time, and blocks nothing user-visibleDo you think this needs more advanced scheduling other than one thread for all the sqlite DBs? Do we expect the new metrics to show opportunities here?If there isn't much contention on that thread already then I think it's fine moving it all to the same SequencedTaskRunner.I don't know if there is much contention on DB thread. Hopefully someone can chime in and confirm that the above is what actually happens.If there is contention, it still may make sense to have a single sequence for all. For example we may want to throttle sqlite in a limited threadpool (1 thread?), but at the same time allow disk cache to utilize as many parallel threads as possible for blocking I/O. Without knowing the access pattern I am inclined to just match the current behavior (i.e. one sequence for all DB tasks) and leave the experimentation to whoever is brave (maybe myself, but certainly later). Ideally with Finch.
What matters is that it's provided by post_task.h so that 1) we use a common API everywhere and 2) tasks go through TaskTracker which is where all modern instrumentation/profiling is being added.Ref. lazy_task_runner.h for an API that allows you to have one TaskRunner accessible statically for all your tasks. Having dedicated objects for each logically associated set of tasks is cleaner (even when ignoring scheduling) -- e.g. this is like when we went from global notifications -> ObserverLists.Can we do this without measuring? One particular dragon I am seeing: parallelizing the tasks on the DB thread may have undesired consequences of having more parallel disk I/O (example: spinny disks under heavy seek storms that would block critical reads from the filesystem, such as HTTP disk cache, similar story for cheap eMMC on Android), does the scheduler API have any primitives to address this potential concern?Yes, that's actually another argument for bringing these tasks explicitly to the TaskScheduler. Once the TaskScheduler is aware of all the work, everything is possible.At this stage I am worried about adding more occasional and untestable parallelism on disk without measuring. Also, unclear on how much to invest into expressing parallelization constraints between tasks. With more effort, I can express more, but part of this effort may be wasted.It can dynamically adjust to the current machine's resources (disk, CPU, etc.). Just because things are split on different sequences and *could* run in parallel doesn't mean they actually will, that's the scheduler's decision and it can make a better decision here if there aren't other threads running wild doing their own thing.In practice, TaskScheduler v1 has as many worker threads available for I/O as BlockingPool + CachePool combined previously did, aiming to maintain the status quo initially (or slightly improve it as task priority still has a chance to help in some scenarios), this is nowhere near optimized though -- we will run experiments once we have a full workload, getting to a full workload without regressions is the current goal.please define "full workload". Will it be really status quo? Splitting FILE/DB threads into multiple sequences governed by a single threadpool is a different system that may perform significantly differently, no?
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAJTZ7LJiDrU4i6vyfeK35wf18ntXOXO_b-RXUxKfzZfnAKRF%3Dw%40mail.gmail.com.
--Egor Pasko--Egor Pasko
Top-level comment: note that splitting concerns isn't only about being able to run more things in parallel; it's also (and even more so) about being able to run only what matters under crunch. Currently we have to run everything to get to what matters because work is queued in FIFO on a single sequence (which also causes jank dependencies between unrelated systems).On Wed, Jun 14, 2017 at 2:55 PM Egor Pasko <pa...@google.com> wrote:On Wed, Jun 14, 2017 at 8:30 PM, Gabriel Charette <g...@chromium.org> wrote:On Wed, Jun 14, 2017 at 2:16 PM Egor Pasko <pa...@google.com> wrote:I've got a review for some bits of DB thread migration and I realized that I do not know enough about the DB thread to make the right call.We can make a sequence per sqlite DB, this would be pretty straightforward. Is it the current recommendation? While this helps with code health and potential metrics, I don't think it would open any new scheduling opportunities.The pattern I saw in a few places is:1. read all contents of the DB into RAM on initialization2. on updates of this working set, throw a task to DB thread to flush the delta to disk3. (optionally) throttle somewhat to reduce amount of flushes (powering up disks, etc), but still provide some persistency guarantees (which are specific to particular sqlite DB)4. the DB thread is mostly idle most of the time, and blocks nothing user-visibleDo you think this needs more advanced scheduling other than one thread for all the sqlite DBs? Do we expect the new metrics to show opportunities here?If there isn't much contention on that thread already then I think it's fine moving it all to the same SequencedTaskRunner.I don't know if there is much contention on DB thread. Hopefully someone can chime in and confirm that the above is what actually happens.If there is contention, it still may make sense to have a single sequence for all. For example we may want to throttle sqlite in a limited threadpool (1 thread?), but at the same time allow disk cache to utilize as many parallel threads as possible for blocking I/O. Without knowing the access pattern I am inclined to just match the current behavior (i.e. one sequence for all DB tasks) and leave the experimentation to whoever is brave (maybe myself, but certainly later). Ideally with Finch.Disk cache is currently running at TaskPriority::USER_BLOCKING so it will get ahead of anything marked with a lower priority (even up to using all the available workers under load). I'm fine leaving it as-is with a static task runner, at this point we mostly care about getting rid of the static BrowserThread::IDs.
What matters is that it's provided by post_task.h so that 1) we use a common API everywhere and 2) tasks go through TaskTracker which is where all modern instrumentation/profiling is being added.Ref. lazy_task_runner.h for an API that allows you to have one TaskRunner accessible statically for all your tasks. Having dedicated objects for each logically associated set of tasks is cleaner (even when ignoring scheduling) -- e.g. this is like when we went from global notifications -> ObserverLists.Can we do this without measuring? One particular dragon I am seeing: parallelizing the tasks on the DB thread may have undesired consequences of having more parallel disk I/O (example: spinny disks under heavy seek storms that would block critical reads from the filesystem, such as HTTP disk cache, similar story for cheap eMMC on Android), does the scheduler API have any primitives to address this potential concern?Yes, that's actually another argument for bringing these tasks explicitly to the TaskScheduler. Once the TaskScheduler is aware of all the work, everything is possible.At this stage I am worried about adding more occasional and untestable parallelism on disk without measuring. Also, unclear on how much to invest into expressing parallelization constraints between tasks. With more effort, I can express more, but part of this effort may be wasted.It can dynamically adjust to the current machine's resources (disk, CPU, etc.). Just because things are split on different sequences and *could* run in parallel doesn't mean they actually will, that's the scheduler's decision and it can make a better decision here if there aren't other threads running wild doing their own thing.In practice, TaskScheduler v1 has as many worker threads available for I/O as BlockingPool + CachePool combined previously did, aiming to maintain the status quo initially (or slightly improve it as task priority still has a chance to help in some scenarios), this is nowhere near optimized though -- we will run experiments once we have a full workload, getting to a full workload without regressions is the current goal.please define "full workload". Will it be really status quo? Splitting FILE/DB threads into multiple sequences governed by a single threadpool is a different system that may perform significantly differently, no?That's a good point, we could restrict work that isn't TaskPriority::USER_BLOCKING to a max of 3 threads to simulate the current system if that feels more "status quo".
AFAIK though disks perform better when the kernel is aware of all the pending I/O requests
so parallelization shouldn't be a bad thing (especially when coupled with I/O priority at kernel level but I think that's a Windows-only thing).
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAJTZ7LJiDrU4i6vyfeK35wf18ntXOXO_b-RXUxKfzZfnAKRF%3Dw%40mail.gmail.com.
--Egor Pasko--Egor Pasko
On Wed, Jun 14, 2017 at 9:54 PM, Gabriel Charette <g...@chromium.org> wrote:Top-level comment: note that splitting concerns isn't only about being able to run more things in parallel; it's also (and even more so) about being able to run only what matters under crunch. Currently we have to run everything to get to what matters because work is queued in FIFO on a single sequence (which also causes jank dependencies between unrelated systems).On Wed, Jun 14, 2017 at 2:55 PM Egor Pasko <pa...@google.com> wrote:On Wed, Jun 14, 2017 at 8:30 PM, Gabriel Charette <g...@chromium.org> wrote:On Wed, Jun 14, 2017 at 2:16 PM Egor Pasko <pa...@google.com> wrote:I've got a review for some bits of DB thread migration and I realized that I do not know enough about the DB thread to make the right call.We can make a sequence per sqlite DB, this would be pretty straightforward. Is it the current recommendation? While this helps with code health and potential metrics, I don't think it would open any new scheduling opportunities.The pattern I saw in a few places is:1. read all contents of the DB into RAM on initialization2. on updates of this working set, throw a task to DB thread to flush the delta to disk3. (optionally) throttle somewhat to reduce amount of flushes (powering up disks, etc), but still provide some persistency guarantees (which are specific to particular sqlite DB)4. the DB thread is mostly idle most of the time, and blocks nothing user-visibleDo you think this needs more advanced scheduling other than one thread for all the sqlite DBs? Do we expect the new metrics to show opportunities here?If there isn't much contention on that thread already then I think it's fine moving it all to the same SequencedTaskRunner.I don't know if there is much contention on DB thread. Hopefully someone can chime in and confirm that the above is what actually happens.If there is contention, it still may make sense to have a single sequence for all. For example we may want to throttle sqlite in a limited threadpool (1 thread?), but at the same time allow disk cache to utilize as many parallel threads as possible for blocking I/O. Without knowing the access pattern I am inclined to just match the current behavior (i.e. one sequence for all DB tasks) and leave the experimentation to whoever is brave (maybe myself, but certainly later). Ideally with Finch.Disk cache is currently running at TaskPriority::USER_BLOCKING so it will get ahead of anything marked with a lower priority (even up to using all the available workers under load). I'm fine leaving it as-is with a static task runner, at this point we mostly care about getting rid of the static BrowserThread::IDs.I think this is not true. I believe the disk subsystem in the kernel ignores this priority setting. So in effect, even though the cache tasks will be scheduled, their access to disk would be slowed down if a lot of concurrent disk I/O is happening, regardless of how low the priorities of those other threads are.
What matters is that it's provided by post_task.h so that 1) we use a common API everywhere and 2) tasks go through TaskTracker which is where all modern instrumentation/profiling is being added.Ref. lazy_task_runner.h for an API that allows you to have one TaskRunner accessible statically for all your tasks. Having dedicated objects for each logically associated set of tasks is cleaner (even when ignoring scheduling) -- e.g. this is like when we went from global notifications -> ObserverLists.Can we do this without measuring? One particular dragon I am seeing: parallelizing the tasks on the DB thread may have undesired consequences of having more parallel disk I/O (example: spinny disks under heavy seek storms that would block critical reads from the filesystem, such as HTTP disk cache, similar story for cheap eMMC on Android), does the scheduler API have any primitives to address this potential concern?Yes, that's actually another argument for bringing these tasks explicitly to the TaskScheduler. Once the TaskScheduler is aware of all the work, everything is possible.At this stage I am worried about adding more occasional and untestable parallelism on disk without measuring. Also, unclear on how much to invest into expressing parallelization constraints between tasks. With more effort, I can express more, but part of this effort may be wasted.It can dynamically adjust to the current machine's resources (disk, CPU, etc.). Just because things are split on different sequences and *could* run in parallel doesn't mean they actually will, that's the scheduler's decision and it can make a better decision here if there aren't other threads running wild doing their own thing.In practice, TaskScheduler v1 has as many worker threads available for I/O as BlockingPool + CachePool combined previously did, aiming to maintain the status quo initially (or slightly improve it as task priority still has a chance to help in some scenarios), this is nowhere near optimized though -- we will run experiments once we have a full workload, getting to a full workload without regressions is the current goal.please define "full workload". Will it be really status quo? Splitting FILE/DB threads into multiple sequences governed by a single threadpool is a different system that may perform significantly differently, no?That's a good point, we could restrict work that isn't TaskPriority::USER_BLOCKING to a max of 3 threads to simulate the current system if that feels more "status quo".Strictly speaking it's not 100% the same as the current setup, but it's super close and is a good recommendation, hence it answers my original question. I think we should add it to the migration docs about FILE/DB migration (unless someone else on this list shares better insights).
AFAIK though disks perform better when the kernel is aware of all the pending I/O requestsThis is certainly not true :) The kernel does not know what the FTL is doing and makes poor choices in a lot of cases. I should, of course, be equally skeptical about Chrome's ability to schedule disk I/O jobs in FTL-friendly way, and in userspace, oh oh. The only thing we can do better is to know what is user-blocking.so parallelization shouldn't be a bad thing (especially when coupled with I/O priority at kernel level but I think that's a Windows-only thing).On Linux/Android the information about which thread requested/dirtied the OS page cache is mostly ignored at I/O scheduling level. CFQ has some knobs for per-cgroup scheduling, but it's not used on Android, I believe.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAJTZ7LJiDrU4i6vyfeK35wf18ntXOXO_b-RXUxKfzZfnAKRF%3Dw%40mail.gmail.com.
--Egor Pasko--Egor Pasko--Egor Pasko
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAJTZ7LJiDrU4i6vyfeK35wf18ntXOXO_b-RXUxKfzZfnAKRF%3Dw%40mail.gmail.com.
--Egor Pasko--Egor Pasko--Egor Pasko
Thanks Egor, let's continue the platform-specific discussion on another thread. Looks like there are discrepancies between what's best on each platform. Overall I think bringing all tasks under a single component is still the right step forward that way each platform's scheduling impl can be specialized for what's best there (even if it turns out that having only a single thread doing I/O is the best, we can easily do that under the hood -- and change our minds later without having to rejig the entire codebase :)). This migration is about labeling every task with TaskTraits and sequencing requirements, that doesn't necessarily mean more parallelism, it merely means more ability to control.On Thu, Jun 15, 2017 at 5:52 AM Egor Pasko <pa...@google.com> wrote:On Wed, Jun 14, 2017 at 9:54 PM, Gabriel Charette <g...@chromium.org> wrote:Top-level comment: note that splitting concerns isn't only about being able to run more things in parallel; it's also (and even more so) about being able to run only what matters under crunch. Currently we have to run everything to get to what matters because work is queued in FIFO on a single sequence (which also causes jank dependencies between unrelated systems).On Wed, Jun 14, 2017 at 2:55 PM Egor Pasko <pa...@google.com> wrote:On Wed, Jun 14, 2017 at 8:30 PM, Gabriel Charette <g...@chromium.org> wrote:On Wed, Jun 14, 2017 at 2:16 PM Egor Pasko <pa...@google.com> wrote:I've got a review for some bits of DB thread migration and I realized that I do not know enough about the DB thread to make the right call.We can make a sequence per sqlite DB, this would be pretty straightforward. Is it the current recommendation? While this helps with code health and potential metrics, I don't think it would open any new scheduling opportunities.The pattern I saw in a few places is:1. read all contents of the DB into RAM on initialization2. on updates of this working set, throw a task to DB thread to flush the delta to disk3. (optionally) throttle somewhat to reduce amount of flushes (powering up disks, etc), but still provide some persistency guarantees (which are specific to particular sqlite DB)4. the DB thread is mostly idle most of the time, and blocks nothing user-visibleDo you think this needs more advanced scheduling other than one thread for all the sqlite DBs? Do we expect the new metrics to show opportunities here?If there isn't much contention on that thread already then I think it's fine moving it all to the same SequencedTaskRunner.I don't know if there is much contention on DB thread. Hopefully someone can chime in and confirm that the above is what actually happens.If there is contention, it still may make sense to have a single sequence for all. For example we may want to throttle sqlite in a limited threadpool (1 thread?), but at the same time allow disk cache to utilize as many parallel threads as possible for blocking I/O. Without knowing the access pattern I am inclined to just match the current behavior (i.e. one sequence for all DB tasks) and leave the experimentation to whoever is brave (maybe myself, but certainly later). Ideally with Finch.Disk cache is currently running at TaskPriority::USER_BLOCKING so it will get ahead of anything marked with a lower priority (even up to using all the available workers under load). I'm fine leaving it as-is with a static task runner, at this point we mostly care about getting rid of the static BrowserThread::IDs.I think this is not true. I believe the disk subsystem in the kernel ignores this priority setting. So in effect, even though the cache tasks will be scheduled, their access to disk would be slowed down if a lot of concurrent disk I/O is happening, regardless of how low the priorities of those other threads are.This last paragraph was referring to Chrome's TaskScheduler so I can vouch that it is true on all platforms.
What matters is that it's provided by post_task.h so that 1) we use a common API everywhere and 2) tasks go through TaskTracker which is where all modern instrumentation/profiling is being added.Ref. lazy_task_runner.h for an API that allows you to have one TaskRunner accessible statically for all your tasks. Having dedicated objects for each logically associated set of tasks is cleaner (even when ignoring scheduling) -- e.g. this is like when we went from global notifications -> ObserverLists.Can we do this without measuring? One particular dragon I am seeing: parallelizing the tasks on the DB thread may have undesired consequences of having more parallel disk I/O (example: spinny disks under heavy seek storms that would block critical reads from the filesystem, such as HTTP disk cache, similar story for cheap eMMC on Android), does the scheduler API have any primitives to address this potential concern?Yes, that's actually another argument for bringing these tasks explicitly to the TaskScheduler. Once the TaskScheduler is aware of all the work, everything is possible.At this stage I am worried about adding more occasional and untestable parallelism on disk without measuring. Also, unclear on how much to invest into expressing parallelization constraints between tasks. With more effort, I can express more, but part of this effort may be wasted.It can dynamically adjust to the current machine's resources (disk, CPU, etc.). Just because things are split on different sequences and *could* run in parallel doesn't mean they actually will, that's the scheduler's decision and it can make a better decision here if there aren't other threads running wild doing their own thing.In practice, TaskScheduler v1 has as many worker threads available for I/O as BlockingPool + CachePool combined previously did, aiming to maintain the status quo initially (or slightly improve it as task priority still has a chance to help in some scenarios), this is nowhere near optimized though -- we will run experiments once we have a full workload, getting to a full workload without regressions is the current goal.please define "full workload". Will it be really status quo? Splitting FILE/DB threads into multiple sequences governed by a single threadpool is a different system that may perform significantly differently, no?That's a good point, we could restrict work that isn't TaskPriority::USER_BLOCKING to a max of 3 threads to simulate the current system if that feels more "status quo".Strictly speaking it's not 100% the same as the current setup, but it's super close and is a good recommendation, hence it answers my original question. I think we should add it to the migration docs about FILE/DB migration (unless someone else on this list shares better insights).How to best optimize I/O is a platform-specific decision, I'm not sure why we'd need to document it in the migration docs (which are about bringing all tasks to the API).
AFAIK though disks perform better when the kernel is aware of all the pending I/O requestsThis is certainly not true :) The kernel does not know what the FTL is doing and makes poor choices in a lot of cases. I should, of course, be equally skeptical about Chrome's ability to schedule disk I/O jobs in FTL-friendly way, and in userspace, oh oh. The only thing we can do better is to know what is user-blocking.so parallelization shouldn't be a bad thing (especially when coupled with I/O priority at kernel level but I think that's a Windows-only thing).On Linux/Android the information about which thread requested/dirtied the OS page cache is mostly ignored at I/O scheduling level. CFQ has some knobs for per-cgroup scheduling, but it's not used on Android, I believe.Interesting, it's certainly true on Windows (have seen it many times in ETW (low-level) traces -- the kernel is amazing at juggling I/O priority (which is different from thread priority on Windows).
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
If the philosophy is "you may crash at any moment", then it seems like just about any task that doesn't touch state that will be deleted during orderly shutdown should be CONTINUE_ON_SHUTDOWN. Does this seem like good guidance? Would you go so far as to put this in a "best practices" doc?
Another question: I just reviewed some code that posts a MayBlock() task and handles the reply back on the main thread. I think this is fairly typical. In this case, the blocking function is not implemented in the same module as the code that posts the task. It seems like a layering violation for the code calling PostTask to decide whether to CONTINUE or SKIP on shutdown, since it really depends on how it's implemented. Have you scheduler folks thought about graceful ways to handle this?
On Fri, Jun 23, 2017 at 3:58 AM Greg Thompson <g...@chromium.org> wrote:If the philosophy is "you may crash at any moment", then it seems like just about any task that doesn't touch state that will be deleted during orderly shutdown should be CONTINUE_ON_SHUTDOWN. Does this seem like good guidance? Would you go so far as to put this in a "best practices" doc?The philosophy is not quite "you may crash at any moment", it's "you should be able to crash at any moment but should do your best to preserve state and coalesce things that will make the next startup smoother".On desktop, shutdown still goes all the way until main() unfolds, static un-initialization occurs, etc. As such it's dangerous to recommend CONTINUE_ON_SHUTDOWN as a default as it can blow up for any task that touches static state or non-leaky LazyInstance/Singleton from a worker thread that outlives the main thread. I have a strong opinion that we should terminate process earlier instead of unwinding everything (don't clean the carpets before burning down the building), discussed a few times on chromium-dev already. However this is another topic and not one we were willing to mix with the task scheduler migration (big enough on its own!).Until then, SKIP_ON_SHUTDOWN is preferred for anything that doesn't persist critical state.Ultimately once everything is in the TaskScheduler our vision is to drive towards what we call "atomic shutdown": since there are no named threads to be joined in order, the TaskScheduler can execute all BLOCK_SHUTDOWN work and then terminate process, no service outlives another. Shutdown is then merely a shutdown broadcast signal to registred services, followed by TaskScheduler::Shutdown() which blocks until BLOCK_SHUTDOWN work is done (allowing communication amongst services to flush things), followed by TerminateProcess().PS: Yes some ordering requirements will need to stick to make sure we don't flush the same thing multiple times on last minute updates.Another question: I just reviewed some code that posts a MayBlock() task and handles the reply back on the main thread. I think this is fairly typical. In this case, the blocking function is not implemented in the same module as the code that posts the task. It seems like a layering violation for the code calling PostTask to decide whether to CONTINUE or SKIP on shutdown, since it really depends on how it's implemented. Have you scheduler folks thought about graceful ways to handle this?We believe this is no different than having to request that the task run in a context that allows I/O (i.e. base::MayBlock() permits base::AssertIOAllowed()). Whether it should block shutdown is more of a decision for the caller IMO, the task itself should verify safety requirements (i.e., again, AssertIOAllowed()) as such we never believed a base::AssertShutdownBehavior(TaskShutdownBehavior behavior); method was necessary but maybe a base::AssertTaskCantOutliveMain() or something is useful (i.e. assert !CONTINUE_ON_SHUTOWN) as that's the only dangerous thing a task may have a dependency on regarding its environment's TaskShutdownBehavior. We haven't added that to date as CONTINUE_ON_SHUTDOWN == SKIP_ON_SHUTDOWN in aforementioned "atomic shutdown" world but it might be a good thing in the meantime, WDYT?
What you express is identical to the pre-existing AssertIOAllowed() though (e.g. we decided long ago that registry access on Windows didn't involve I/O and remove the restriction there but some old code still hops to the FILE thread today to do registry operations).
I'm not saying this is great, but it's a pre-existing paradigm in chromium to request an execution context from the caller and have assertions in the tasks to confirm it's what they got. We hope to make this more local with the new API (per encouraging creating a task runner in the leaf components as fits instead of requesting a plumbed runner with specific traits), but we aren't completely removing this paradigm either (and regarding shutdown behaviors, this was also true before with SequencedWorkerPool).
Re. WDYT of an assert for shutdown safety?
I believe that the code that posts a task should decide whether the task has to be scheduled before shutdown completes while the task itself should decide whether shutdown can complete while it is running.
What do you think of this API change?1. Replace the TaskShutdownBehavior trait with a MustBeScheduledBeforeShutdown() trait.
E.g.// TaskA will be scheduled before shutdown completes.base::PostTaskWithTraits(FROM_HERE, {base::MustBeScheduledBeforeShutdown()}, base::BindOnce(&TaskA));// Shutdown can complete before TaskB is scheduled. No task is scheduled once shutdown is complete.base::PostTaskWithTraits(FROM_HERE, {}, base::BindOnce(&TaskB));2. Add base::AllowShutdownToComplete().
E.g.void TaskA() {PersistStateOnDisk();base::AllowShutdownToComplete();DoMoreWorkThatIsNotSoImportant();}void TaskB() {DoSomeWorkThatAssumesThatShutdownIsNotComplete();base::AllowShutdownToComplete();LongOperationThatShouldNotBlockShutdown();}Unless someone can think of a reason to have a task that must be scheduled before shutdown other than to persist state, base::MustBeScheduledBeforeShutdown() could be base::PersistsState().
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAJTZ7LJHwqSuZ3-McE7byMpmrg1eKYwWFpnKk5zyv%3D0qJPmRNQ%40mail.gmail.com.To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
I have the same issue as Greg. The service worker database task manager allows for mixed shutdown behaviors in order to support the "Clear data on exit" browsing setting, which requires deleting service workers when the browser/profile exits. We settled on this design in the code review: https://codereview.chromium.org/633873002
Are you saying this design doesn't work today, and even though we use the same sequence token, the tasks are not necessarily run in the order they are posted?
Do you plan on adding the feature someday? If so, it seems like for this particular issue, we might just make all tasks BLOCK_SHUTDOWN until we can reliably make only the "Clear on exit" task block shutdown.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
On Sun, Jul 23, 2017 at 11:27 PM Matt Falkenhagen <fal...@chromium.org> wrote:I have the same issue as Greg. The service worker database task manager allows for mixed shutdown behaviors in order to support the "Clear data on exit" browsing setting, which requires deleting service workers when the browser/profile exits. We settled on this design in the code review: https://codereview.chromium.org/633873002I assume this is the code you are referring to: https://chromium.googlesource.com/chromium/src/+/ca2051b6170d833a504c8b2d9138a4171d64b8c9/content/browser/service_worker/service_worker_database_task_manager.cc#14
Are you saying this design doesn't work today, and even though we use the same sequence token, the tasks are not necessarily run in the order they are posted?Tasks posted with the same sequence token are guaranteed to run one at a time in posting order.However, creating SequencedTaskRunners with the same sequence token but different shutdown behaviors is not supported. All SequencedTaskRunners created with the same sequence token will have the shutdown behavior of the first SequencedTaskRunner created with that sequence token.Do you plan on adding the feature someday? If so, it seems like for this particular issue, we might just make all tasks BLOCK_SHUTDOWN until we can reliably make only the "Clear on exit" task block shutdown.Yes, we plan to add this feature someday.In the meantime, making all tasks BLOCK_SHUTDOWN is a good solution (FYI, GetSequencedTaskRunner creates a BLOCK_SHUTDOWN, so all tasks have always been BLOCK_SHUTDOWN anyways source).
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
// Note: this a hack and only works if no delayd tasks were ever posted to
// |background_runner_|.
scoped_refptr<base::DeferredSequencedTaskRunner> new_runner(
base::MakeRefCounted<base::DeferredSequencedTaskRunner>(
base::CreateSequencedTaskRunnerWithTraits({ ..... })));
// Only Start() |new_runner| after all pending tasks on |background_runner_|
// have completed. Note: you will also need to DetachFrom(Sequence|Thread)() any
// associated (Sequence|Thread)Checker right before Start() so you may want to
// bind a helper here instead of a direct call to Start().
background_runner_->PostTask(
FROM_HERE,
base::Bind(&base::DeferredSequencedTaskRunner::Start, new_runner));
// Post all new tasks to |new_runner|.
background_runner_ = new_runner;
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.