I presume the data will be changing frequently in memory. How often
are you going to be writing it out to disk? Are you going to wear out
some SSDs? ;-)
The mapped page writer thread writes dirty pages from mapped files out to their backing store at timed intervals. In Windows Vista and later Windows releases, the mapped page writer sweeps through the dirty page list at regular intervals and flushes all the pages out to their backing store. If the number of free pages is low, the system accelerates the sweep by using a shorter interval. In earlier Windows releases, the mapped page writer flushed everything at absolute 5-minute intervals. Windows Vista writes dirty pages sooner than earlier Windows releases and the write operations typically involve less data.
> --
On Fri, Oct 16, 2015 at 11:27 AM, 'Brian White' via Chromium-dev
<chromi...@chromium.org> wrote:
> I have a use-case (UMA metrics) where we're considering writing the values
> to file-backed memory so that metrics gathered during activities like
> shutdown and install can be persistently stored and forwarded next time
> Chrome is running normally.
>
> Would it be reasonable to extend MemoryMappedFile to allow read/write
> access?
>
> The reason for using an mmap'd file is speed. UMA histograms have to be
> extremely low overhead and typically boil down to a few (predictable) jumps,
> a couple pointer dereferences, and an incremented atomic integer. Having
> direct memory access to these is important and letting the OS flush out
> dirty pages at its convenience means less impact on Chrome itself.
>
> Brian
> bcw...@google.com
> -----------------------------------------------------------------------------------------
> Treat someone as they are and they will remain that way.
> Treat someone as they can be and they will become that way.
>
> --
> Chromium Developers mailing list: chromi...@chromium.org
> View archives, change email options, or unsubscribe:
> http://groups.google.com/a/chromium.org/group/chromium-dev
So how often are you going to be writing out to disk? For preferences
as an example, Chromium keeps the data in memory as a DictionaryValue
(I think), and serialize to JSON when it writes it out to disk
periodically.
--
The OS is also allowed to write the pages to disk out of order, and if the machine crashes you might have persisted an inconsistent view of memory. Does that matter for your use case and/or do you have plans for how to address it?
I presume the data will be changing frequently in memory. How often
are you going to be writing it out to disk? Are you going to wear out
some SSDs? ;-)Linux, at least, doesn't guarantee any write-back of dirty pages until the file becomes unmapped unless an explicit msync() call is made.
I presume the data will be changing frequently in memory. How often
are you going to be writing it out to disk? Are you going to wear out
some SSDs? ;-)Linux, at least, doesn't guarantee any write-back of dirty pages until the file becomes unmapped unless an explicit msync() call is made.The other aspect is also important, could these prevent a disk from going to sleep that would otherwise have gone to sleep?
I presume the data will be changing frequently in memory. How often
are you going to be writing it out to disk? Are you going to wear out
some SSDs? ;-)Linux, at least, doesn't guarantee any write-back of dirty pages until the file becomes unmapped unless an explicit msync() call is made.
I presume the data will be changing frequently in memory. How often
are you going to be writing it out to disk? Are you going to wear out
some SSDs? ;-)Linux, at least, doesn't guarantee any write-back of dirty pages until the file becomes unmapped unless an explicit msync() call is made.It doesn't *guarantee* it unless msync(), but there is a kernel thread which goes around cleaning dirty pages to keep them to a manageable number, and so you can't really make any assumptions about causing minimal wear; it is perfectly legitimate for the kernel to instantly flush every single individual write you make to disk.
There are probably histograms logged from background posted tasks. Histogram use is extensive throughout Chrome, so I wouldn't be surprised if there are things like that.
I think there's definitely a lot of "gotchas" with such an approach and some of them we'll just have to dig into once we have a working prototype of this. Then we can figure out what the actual impact is instead of speculating about it.
I presume the data will be changing frequently in memory. How often
are you going to be writing it out to disk? Are you going to wear out
some SSDs? ;-)Linux, at least, doesn't guarantee any write-back of dirty pages until the file becomes unmapped unless an explicit msync() call is made.It doesn't *guarantee* it unless msync(), but there is a kernel thread which goes around cleaning dirty pages to keep them to a manageable number, and so you can't really make any assumptions about causing minimal wear; it is perfectly legitimate for the kernel to instantly flush every single individual write you make to disk.Right. But as you said, it is only trying to keep it to a manageable number. This won't be the first time mmap'd files are used this way. The OS certainly has SSDs in mind when determining write policies.
I presume the data will be changing frequently in memory. How often
are you going to be writing it out to disk? Are you going to wear out
some SSDs? ;-)Linux, at least, doesn't guarantee any write-back of dirty pages until the file becomes unmapped unless an explicit msync() call is made.It doesn't *guarantee* it unless msync(), but there is a kernel thread which goes around cleaning dirty pages to keep them to a manageable number, and so you can't really make any assumptions about causing minimal wear; it is perfectly legitimate for the kernel to instantly flush every single individual write you make to disk.Right. But as you said, it is only trying to keep it to a manageable number. This won't be the first time mmap'd files are used this way. The OS certainly has SSDs in mind when determining write policies.Sadly I think you're being very optimistic there and the kernel flush daemon pretty much only cares about numbers of memory pages in different states (in total, across the whole system) and will do whatever it needs to do to make those numbers be in ratios it likes, with somewhere between "little" and "absolutely no" consideration of which block device even backs any given page, let alone whether it's an SSD. :/
One way to minimize this class of concern would be to have these be a new kind of histogram, then be selective about what gets to live in that bin, rather than worrying about problems which might be caused by high-volume histograms using memory-mapped files.
Yes, the wink when I brought up SSDs means it's not a serious concern.
I'm still trying to understand how frequently data needs to be written
out to disk.
Does using ImportantFileWriter to periodically write it out work for you then?
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
> Problems I can think of off-hand:
>
> It would have to be instantiated in other programs, too, such as setup.exe.
> You could then have a race condition.
Hrm, I missed your earlier comment about "be accessible by multiple
processes (i.e. browser, rendered, setup, etc.)" What does
"accessible" mean exactly? Is everyone a reader? Is everyone a writer?
Are there multiple writers? Don't forget most processes are generally
sandboxed and don't have direct access to disk. The question started
out as mmaping files, but this requirement makes the issue more
complicated. Care to list all the requirements?
Important questions with file backed data:
1. Generally: what is your access pattern?
2. Particularly: how many 4K pages, how frequently the data is supposed to be read / updated?
3. How much consistency / availability is necessary? Do we wipe off all the data if it's inconsistent? How expensive is the consistency check? (inconsistency may come from crashes, memory reordering, less likely: bit flips in RAM or on the block device)
Trying to answer (1): histograms are used on all threads (UI and IO threads included), and it's critical to never delay recording them. With file backed memory we don't have any guarantees on data availability. On a busy system it may take a 100ms to fetch the page from disk just to record 8 bytes of your histogram. I would consider these long tail delays highly undesirable.
> Problems I can think of off-hand:
>
> It would have to be instantiated in other programs, too, such as setup.exe.
> You could then have a race condition.
Hrm, I missed your earlier comment about "be accessible by multiple
processes (i.e. browser, rendered, setup, etc.)" What does
"accessible" mean exactly? Is everyone a reader? Is everyone a writer?
Are there multiple writers? Don't forget most processes are generally
sandboxed and don't have direct access to disk. The question started
out as mmaping files, but this requirement makes the issue more
complicated. Care to list all the requirements?
Sure. This thread was just about a part of a design discussed with my colleagues but if we're going to a full design review, here's the (start of a) design doc:I was about to start a second thread asking if there was existing code to do malloc/free equivalents within a designated memory block. ???If the renderer can't access a file even to memory-map it at start-up, then that effectively eliminates memory-mapped files as the persistent storage mechanism. The (first) alternative would be a simple shared-memory block, unbacked by disk. This would cover all the cases except keeping stats across logout/shutdown... but that can be added at a later time.Important questions with file backed data:
1. Generally: what is your access pattern?
2. Particularly: how many 4K pages, how frequently the data is supposed to be read / updated?
3. How much consistency / availability is necessary? Do we wipe off all the data if it's inconsistent? How expensive is the consistency check? (inconsistency may come from crashes, memory reordering, less likely: bit flips in RAM or on the block device)Trying to answer (1): histograms are used on all threads (UI and IO threads included), and it's critical to never delay recording them. With file backed memory we don't have any guarantees on data availability. On a busy system it may take a 100ms to fetch the page from disk just to record 8 bytes of your histogram. I would consider these long tail delays highly undesirable.All memory is backed by disk these days
so you always have that risk, even in the current implementation. Frequently accessed histograms would be unlikely to become unpinned. In fact, since they'd all reside within the same few pages, even the infrequently accessed ones wouldn't become unpinned.It's also possible that the situation would improve because, today, a histogram could be allocated as part of a page containing only infrequently accessed memory that easily gets swapped out.However, all of the benefits can be achieved with any shared memory scheme. It doesn't have to be a memory-mapped file; that just seemed easiest, at least to start.Brian
bcw...@google.com
-----------------------------------------------------------------------------------------
Treat someone as they are and they will remain that way.
Treat someone as they can be and they will become that way.
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
On Tue, Oct 20, 2015 at 2:20 PM, 'Brian White' via Chromium-dev <chromi...@chromium.org> wrote:> Problems I can think of off-hand:
>
> It would have to be instantiated in other programs, too, such as setup.exe.
> You could then have a race condition.
Hrm, I missed your earlier comment about "be accessible by multiple
processes (i.e. browser, rendered, setup, etc.)" What does
"accessible" mean exactly? Is everyone a reader? Is everyone a writer?
Are there multiple writers? Don't forget most processes are generally
sandboxed and don't have direct access to disk. The question started
out as mmaping files, but this requirement makes the issue more
complicated. Care to list all the requirements?
Sure. This thread was just about a part of a design discussed with my colleagues but if we're going to a full design review, here's the (start of a) design doc:I was about to start a second thread asking if there was existing code to do malloc/free equivalents within a designated memory block. ???If the renderer can't access a file even to memory-map it at start-up, then that effectively eliminates memory-mapped files as the persistent storage mechanism. The (first) alternative would be a simple shared-memory block, unbacked by disk. This would cover all the cases except keeping stats across logout/shutdown... but that can be added at a later time.Important questions with file backed data:
1. Generally: what is your access pattern?
2. Particularly: how many 4K pages, how frequently the data is supposed to be read / updated?
3. How much consistency / availability is necessary? Do we wipe off all the data if it's inconsistent? How expensive is the consistency check? (inconsistency may come from crashes, memory reordering, less likely: bit flips in RAM or on the block device)Trying to answer (1): histograms are used on all threads (UI and IO threads included), and it's critical to never delay recording them. With file backed memory we don't have any guarantees on data availability. On a busy system it may take a 100ms to fetch the page from disk just to record 8 bytes of your histogram. I would consider these long tail delays highly undesirable.All memory is backed by disk these daysI could not find it easily in the code. Any pointers?
Actually wow, sounds like lots of sources for random jank everywhere, I am scared now.
Trying to answer (1): histograms are used on all threads (UI and IO threads included), and it's critical to never delay recording them. With file backed memory we don't have any guarantees on data availability. On a busy system it may take a 100ms to fetch the page from disk just to record 8 bytes of your histogram. I would consider these long tail delays highly undesirable.All memory is backed by disk these daysI could not find it easily in the code. Any pointers?Modern operating systems assume all memory can be paged, either using the file it's mapped from if it's mapped from a file, or using swap if it's not, except in very special scenarios where you've demanded things be locked in RAM (typically for crypto use cases). There's nothing to find in our code, the kernel is doing it. :)Actually wow, sounds like lots of sources for random jank everywhere, I am scared now.Yes, this has been the case since people started doing paging in kernels. You have little control over when you will block on disk IO.
Trying to answer (1): histograms are used on all threads (UI and IO threads included), and it's critical to never delay recording them. With file backed memory we don't have any guarantees on data availability. On a busy system it may take a 100ms to fetch the page from disk just to record 8 bytes of your histogram. I would consider these long tail delays highly undesirable.All memory is backed by disk these daysI could not find it easily in the code. Any pointers?Modern operating systems assume all memory can be paged, either using the file it's mapped from if it's mapped from a file, or using swap if it's not, except in very special scenarios where you've demanded things be locked in RAM (typically for crypto use cases). There's nothing to find in our code, the kernel is doing it. :)Actually wow, sounds like lots of sources for random jank everywhere, I am scared now.Yes, this has been the case since people started doing paging in kernels. You have little control over when you will block on disk IO.... and is the reason why production machines do not have any default swap. Jobs that want swap (not recommended for anything user-facing) need to create their own swap-file and activate that.
Paging does not require swap. Not having swap just means that memory *not* backed by a file is stuck in physical ram - memory that's backed by a file (e.g. all your actual executable code) is still paged.
On pretty much every system Chromium supports other than the very specific class of Android devices that don't have zram, all memory is backed by disk these days.On that specific class of Android devices, only a substantial chunk of chromium's memory is backed by disk and the rest isn't.
--
On pretty much every system Chromium supports other than the very specific class of Android devices that don't have zram, all memory is backed by disk these days.On that specific class of Android devices, only a substantial chunk of chromium's memory is backed by disk and the rest isn't.Great! So I am very happy with less jank these devices have, and now the proposal is to have more jank in order for UMA histogram data to be persistent? I don't think it is a good tradeoff.
Egor's point is that on Android devices (at least ones without zram) the current memory is never backed by disk, and so making it a memory-mapped file *does* make it backed by disk more than it is currently, even if that's not the case on other platforms.
It is true that putting data in a memory mapped file instead of in allocated memory means that it is more likely to be discarded by the OS and then require reloading from disk.However, if the memory is frequently touched then that won't happen - LRU should prevent it. And, I would expect that the 'priority' of the memory would be comparable to the 'priority' of the code (which is also backed by a file on disk). So, the odds of this file-backed UMA memory getting discarded because it is on disk should be similar to the odds of the code which updates it getting discarded to disk. So, while the risk of a disk access is increased, I don't think it is meaningfully increased.
BTW, there was mention of ImportantFileWriter as a way of maintaining data integrity. This should be reserved for when it is provably needed. I just removed some usage of this on Windows because the overhead (flushing the disk caches after each of many files was written) was exorbitant and the flushes weren't actually needed.
On Wednesday, October 21, 2015 at 12:46:35 PM UTC-4, Richard wrote:Egor's point is that on Android devices (at least ones without zram) the current memory is never backed by disk, and so making it a memory-mapped file *does* make it backed by disk more than it is currently, even if that's not the case on other platforms.On Wed, 21 Oct 2015 at 16:52 Brian White <...> wrote:On pretty much every system Chromium supports other than the very specific class of Android devices that don't have zram, all memory is backed by disk these days.On that specific class of Android devices, only a substantial chunk of chromium's memory is backed by disk and the rest isn't.Great! So I am very happy with less jank these devices have, and now the proposal is to have more jank in order for UMA histogram data to be persistent? I don't think it is a good tradeoff.Definitely don't want more. The shared memory segment wouldn't be backed by disk any more that current memory is. It's possible that grouping the histogram closely in RAM could mean less paging since there's no chance a one could be placed in a page with otherwise infrequently accessed data.It was my hope that a memory-mapped file wouldn't flush pages out to disk on any sort of periodic basis. Thus, it would behave the same as existing RAM. That may not be the case, however, so even though the writes to disk would be async by the OS it would still lead to more disk activity, with all the pitfalls thereof. It may be best to have the shared memory be ram-only with an optional "other" process that persists it to disk should it be appropriate (i.e. all other processes have exited).Brian
bcw...@google.com
-----------------------------------------------------------------------------------------
Treat someone as they are and they will remain that way.
Treat someone as they can be and they will become that way.
It is true that putting data in a memory mapped file instead of in allocated memory means that it is more likely to be discarded by the OS and then require reloading from disk.However, if the memory is frequently touched then that won't happen - LRU should prevent it. And, I would expect that the 'priority' of the memory would be comparable to the 'priority' of the code (which is also backed by a file on disk). So, the odds of this file-backed UMA memory getting discarded because it is on disk should be similar to the odds of the code which updates it getting discarded to disk. So, while the risk of a disk access is increased, I don't think it is meaningfully increased.I agree with that. I think the concern was that the OS would do more writes for file-backed memory that it would with "virtual" memory since there is some expectation that the contents of the file will reflect written data. Windows and Linux both seem to have some sort of background thread that "periodically" flushes dirty pages even if it does not discard them.Additionally, systems without disk-backed memory (e.g. android) will now being doing page flushes when they wouldn't in a simple shared-memory-segment situation. I hear ChromeOS doesn't have VM either. Is that the case?
It is true that putting data in a memory mapped file instead of in allocated memory means that it is more likely to be discarded by the OS and then require reloading from disk.
--
As I understand it the main point of the intended refactor is to tighten up the holes in UMA. So that when a process dies any pending data doesn't necessarily die with it.Keeping these file-backed means we offload this work to the OS and that even the browser process can happily die and still leave behind a usable log of UMA data. However, that may actually be overkill. The main problem is dying renderers, and we don't need their shared memory segments to be file backed as long as the browser also maps them. Given the general concerns about the potential cost of the file I/O I think just keeping these as simple shared memory segments should suffice, and the decision can always be revisited later with actual performance data in hand.
ChrisOn Thu, 22 Oct 2015 at 14:28 Scott Hess <sh...@chromium.org> wrote:--On Thu, Oct 22, 2015 at 11:15 AM, 'Brian White' via Chromium-dev <chromi...@chromium.org> wrote:It is true that putting data in a memory mapped file instead of in allocated memory means that it is more likely to be discarded by the OS and then require reloading from disk.However, if the memory is frequently touched then that won't happen - LRU should prevent it. And, I would expect that the 'priority' of the memory would be comparable to the 'priority' of the code (which is also backed by a file on disk). So, the odds of this file-backed UMA memory getting discarded because it is on disk should be similar to the odds of the code which updates it getting discarded to disk. So, while the risk of a disk access is increased, I don't think it is meaningfully increased.I agree with that. I think the concern was that the OS would do more writes for file-backed memory that it would with "virtual" memory since there is some expectation that the contents of the file will reflect written data. Windows and Linux both seem to have some sort of background thread that "periodically" flushes dirty pages even if it does not discard them.Additionally, systems without disk-backed memory (e.g. android) will now being doing page flushes when they wouldn't in a simple shared-memory-segment situation. I hear ChromeOS doesn't have VM either. Is that the case?I think ChromeOS has zram these days.My impression of the goal of your change is that the entire point is that the OS will be writing things to disk that it otherwise wouldn't have. To me that feels like a good argument to be selective as to which histograms get this treatment. Using shared memory with a dedicated logger would definitely help here - you'd have no impact except in the case when something unexpected happened. It would lose data around OS crashes, though.Another alternative might be to restrict which executions of Chrome get this treatment. Like if 1% (or .01% on stable) were memory-mapped, that might provide enough data to diagnose shutdown problems.Another alternative might be to restrict broad rollout to a specific platform where the downsides are more quantifiable. It would probably be important to land and test the code on all platforms to make sure you don't design yourself into a corner, because once you're persisting data to disk you may find yourself stuck with some decisions. Maybe you'll find that it doesn't provide enough data to be actionable.-scott
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
I am not 100% certain but I don't think that mlock() prevents dirty pages mapped from files being written back to disk. It only prevents them being evicted from memory (which prevents anonymous pages from being written to swap, because that only happens during eviction).
It is true that putting data in a memory mapped file instead of in allocated memory means that it is more likely to be discarded by the OS and then require reloading from disk.
However, if the memory is frequently touched then that won't happen - LRU should prevent it. And, I would expect that the 'priority' of the memory would be comparable to the 'priority' of the code (which is also backed by a file on disk). So, the odds of this file-backed UMA memory getting discarded because it is on disk should be similar to the odds of the code which updates it getting discarded to disk. So, while the risk of a disk access is increased, I don't think it is meaningfully increased.
1. extra disk I/O at unpredictable times (not much, and we piled up a lot of unnecessary disk activity already, not adding disk I/O when possible is a good practice, benchmarking is hard here)
2. value of having this persistent data is not clear: on crashes/OOM/whatnot the data will likely be inconsistent (checksuming individual histograms is possible, but may get histograms disagreeing with one another, for example)
3. with shared memory across processes, cross-process locking is unreliable (see the doc for details)
Ideas on simpler systems that would provide more persistency than we have now:A. have everything as it is now, reuse existing breakpad mechanisms to transfer and persist data on crashes
B. have a mmap-ed file per process, specifically for histograms (files should be open by browser process, and FDs passed to renderers/GPU) - no system-dependent shmem headaches
C. arrange each histogram to know its offset into the 'persistent region' at compile time - then can even use shared memory without allocator and without locking - each histogram updates atomically anyway, just need to reserve a few bits for checksums
I would prefer the option A, if any.
--
For new histograms that are in the process of being created care has to be taken to use "online" data structures, which are always navigable at any point during writes, even in progress. Worst case scenario is a histogram is in mid setup, but you simply navigate past it and ignore it. Not a problem since no data would yet have been stored in it.
You are saying "Locks shouldn't be needed" above, and here you mention dynamic allocation of space for histograms from separate processes.
Assuming that we can solve the problem that shess@ mentioned with growing the area (which looks scary), I would be interested to see a lockfree algorithm for dynamically allocating 4byte chunks in a shared region, using string names as a parameter, making sure that the same name from all processes points to the same chunk. Are you proposing to create another ConcurrentHashMap in the lifetime of this universe or am I missing something? :)
(And saying completely lockless is a bit of lie, as you effectively use a spinlock in performing an allocation, via NoBarrier_CompareAndSwap. Note that this is when carving memory out of an already existing shared memory segment. Acquiring the segment, or a new one when one is full, to begin with can also be done with eventual consistency: the renderer process creates a new segment, starts using it immediately, and asynchronously informs the browser of its existence.)Any "indexing" structure on top of the shared memory can be built as usual, allowing for existing histograms to be found and reused rather than multiply defined in a single process. Such a structure would need locks, but this is no different than what already exists in base/metrics.
The locks are only required in the single process doing the writing: the renderer.
The CompareAndSwap serves both as a lock for multiple writers, and a way to ensure the data structure is always consistent. (And it's not actually to be used as a spin-lock, so no dead lock occurs. It just guards against concurrent writes.) It can be read without locks, which is all the browser will ever need to do.
The questions are more than welcome, as we've put some thought into this, but there's surely things we haven't considered. Many have already been pointed out :)
\On Fri, Oct 23, 2015 at 8:33 PM, Chris Hamilton <chr...@chromium.org> wrote:The locks are only required in the single process doing the writing: the renderer.First reaction: Is this some sort of a single-renderer browser? :)OK, I did not realize that you were talking about every renderer having their own dedicated piece of memory shared with the browser, and even each piece may have some duplication, which would be deduped at upload time. This is not large pieces of memory to duplicate 10 fold, so maybe it's ok.
The CompareAndSwap serves both as a lock for multiple writers, and a way to ensure the data structure is always consistent. (And it's not actually to be used as a spin-lock, so no dead lock occurs. It just guards against concurrent writes.) It can be read without locks, which is all the browser will ever need to do.OK, I think it *might* be possible to create a lockfree hashtable-like structure without remove() that is not too much slower than the current 2 atomic memory references (iirc). Some of its properties (such as memory-wastefulness) are not clear to me, which makes me slightly uncomfortable at the moment. Also the matter relies on base::subtle, which is .. well .. subtle. Building on top of that requires some care and knowledgeable people around.
Also there are some terminological problems in this thread, probably because we are throwing half-baked ideas and nobody designed the concurrency model yet. Let's take another approach: please take time to write your detailed proposal. In the concurrency model please define the use of lowlevel OS primitives (starting from Android please).
I'm convinced the extra disk I/O from occasional page cleaning is a real concern.
\On Fri, Oct 23, 2015 at 8:33 PM, Chris Hamilton <chr...@chromium.org> wrote:The locks are only required in the single process doing the writing: the renderer.First reaction: Is this some sort of a single-renderer browser? :)OK, I did not realize that you were talking about every renderer having their own dedicated piece of memory shared with the browser, and even each piece may have some duplication, which would be deduped at upload time. This is not large pieces of memory to duplicate 10 fold, so maybe it's ok.It may or may not share the same histogram space with all renderers; it hasn't been decided. If so, it's possible (extremely narrow race condition) that multiple
OK, I did not realize that you were talking about every renderer having their own dedicated piece of memory shared with the browser, and even each piece may have some duplication, which would be deduped at upload time. This is not large pieces of memory to duplicate 10 fold, so maybe it's ok.It may or may not share the same histogram space with all renderers; it hasn't been decided. If so, it's possible (extremely narrow race condition) that multipleThere must be no race condition. Narrowness is irrelevant.
sent from phone
On Oct 24, 2015 4:32 PM, "'Brian White' via Chromium-dev" <chromi...@chromium.org> wrote:
>>>>
>>>> OK, I did not realize that you were talking about every renderer having their own dedicated piece of memory shared with the browser, and even each piece may have some duplication, which would be deduped at upload time. This is not large pieces of memory to duplicate 10 fold, so maybe it's ok.
>>>
>>>
>>> It may or may not share the same histogram space with all renderers; it hasn't been decided. If so, it's possible (extremely narrow race condition) that multiple
>>
>>
>> There must be no race condition. Narrowness is irrelevant.
>
>
> Sorry, but that's not the case. Race conditions are fine as long as there are no adverse effects and since we're only concerned with eventual consistency, either outcome of the race is acceptable. One is preferred but not required (as explained in the rest of the paragraph that you omitted from your quote).
I hope there is a misunderstanding caused by different definitions of the term "race condition". Egor is referring to the definition given by the C++ Standard, and such races indeed should not exist in our codebase (not sure this thread is a good place for further discussion of this topic). If I'm understanding correctly, you are referring to a situation with a non-deterministic result, but with synchronized memory accesses, which is ok.
>
> Brian
> bcw...@google.com
> -----------------------------------------------------------------------------------------
> Treat someone as they are and they will remain that way.
> Treat someone as they can be and they will become that way.
>
> Sorry, but that's not the case. Race conditions are fine as long as there are no adverse effects and since we're only concerned with eventual consistency, either outcome of the race is acceptable. One is preferred but not required (as explained in the rest of the paragraph that you omitted from your quote).
I hope there is a misunderstanding caused by different definitions of the term "race condition". Egor is referring to the definition given by the C++ Standard, and such races indeed should not exist in our codebase (not sure this thread is a good place for further discussion of this topic). If I'm understanding correctly, you are referring to a situation with a non-deterministic result, but with synchronized memory accesses, which is ok.
A race condition is a special condition that may occur inside a critical section. A critical section is a section of code that is executed by multiple threads and where the sequence of execution for the threads makes a difference in the result of the concurrent execution of the critical section.
sent from phone
On Oct 24, 2015 4:32 PM, "'Brian White' via Chromium-dev" <chromi...@chromium.org> wrote:
>>>>
>>>> OK, I did not realize that you were talking about every renderer having their own dedicated piece of memory shared with the browser, and even each piece may have some duplication, which would be deduped at upload time. This is not large pieces of memory to duplicate 10 fold, so maybe it's ok.
>>>
>>>
>>> It may or may not share the same histogram space with all renderers; it hasn't been decided. If so, it's possible (extremely narrow race condition) that multiple
>>
>>
>> There must be no race condition. Narrowness is irrelevant.
>
>
> Sorry, but that's not the case. Race conditions are fine as long as there are no adverse effects and since we're only concerned with eventual consistency, either outcome of the race is acceptable. One is preferred but not required (as explained in the rest of the paragraph that you omitted from your quote).
I hope there is a misunderstanding caused by different definitions of the term "race condition". Egor is referring to the definition given by the C++ Standard, and such races indeed should not exist in our codebase (not sure this thread is a good place for further discussion of this topic). If I'm understanding correctly, you are referring to a situation with a non-deterministic result, but with synchronized memory accesses, which is ok.
Also there are some terminological problems in this thread, probably because we are throwing half-baked ideas and nobody designed the concurrency model yet. Let's take another approach: please take time to write your detailed proposal. In the concurrency model please define the use of lowlevel OS primitives (starting from Android please).I have added "Allocation" plans to my document, including pseudo-code. The only low-level primitive is CAS.
> Sorry, but that's not the case. Race conditions are fine as long as there are no adverse effects and since we're only concerned with eventual consistency, either outcome of the race is acceptable. One is preferred but not required (as explained in the rest of the paragraph that you omitted from your quote).
I hope there is a misunderstanding caused by different definitions of the term "race condition". Egor is referring to the definition given by the C++ Standard, and such races indeed should not exist in our codebase (not sure this thread is a good place for further discussion of this topic). If I'm understanding correctly, you are referring to a situation with a non-deterministic result, but with synchronized memory accesses, which is ok.Yes, that's what I mean, thanks, Alexander. Out of curiosity, does TSan support searching for potential race conditions in shared memory used by multiple processes? If not, it could be another reason not to use tricky lockfree stuff in shared memory.
Also there are some terminological problems in this thread, probably because we are throwing half-baked ideas and nobody designed the concurrency model yet. Let's take another approach: please take time to write your detailed proposal. In the concurrency model please define the use of lowlevel OS primitives (starting from Android please).I have added "Allocation" plans to my document, including pseudo-code. The only low-level primitive is CAS.Thanks, that is useful. I found no race conditions, it should probably work (modulo our inability to grow shared memory segment), but will leak memory after each renderer dies. Did you mean some tricky platform-dependent tossing shared memory between renderers to make sure not too much memory is wasted? Otherwise, creating one shmem region per renderer seems simpler.
If the segments are shared across all renderers, then they'll use the same set of histograms without allocating new ones. If they're separate, then the shared memory segment will be discarded when a renderer dies.
Then after that .. not using shmem is almost the same .. and even simpler (sorry, had to say that).
Persisting the data to a file has its own set of problems. But can be accomplished with a single block-write of the memory segment (no longer shared but just allocated as a single block from the heap). At least the main histogram code remains unchanged regardless of the storage mechanism.
In this use case (SyzyAsan) the reader and writer are in the same process, but in different modules. However, in the general case this could be cross process.
Who is the writer going to be? The child process?IIRC on linux if you have two processes which mmap the same fd and one of them ftruncate(fd, 0), the other one will crash (with a SIGBUS IIRC) while trying to access the mmap-ed region (if didn't page fault before) as the underlying backing file has shrunk.If you translate this in chrome terms, the quesiton becomes: can a malicious chilld process ftruncate() the shared fd ? If the answer is yes it means that a malicious renderer can cause the crash of the browser, which sounds bad.
So... To support this use-case... Is there any objection to me adding read/write support to the MemoryMappedFile class?
At the risk of saying something dumb, I'm going to ask a question without having read the preceding part of this thread:Assuming earlier messages have expressed reservations towards the generalized use of these capabilities, how will you add this in a way that prevents other authors in the future from doing (whatever people were worried about)? Just add comments saying "please don't use this unless X"? Or maybe go further and have a subclass of MemoryMappedFile, in some relevant SyzyASAN-related directory, which adds write support, so that only this use case can see and use it?
- start blanket-replacing file I/O with rw-mmaps which looks easier and leaner to use but: (i) Introduces jank on aribtrary threads out of the control of todays's AllowedIO checks. (ii) increases the risk of crashes on corrupted filesystems. read()/write() on a corrupted fs returns an error. mmap() on a corrupted fs causes the entire process to crash (IIRC shess@ has seen this happening for real swithing sqlite from raw IO to mmap)
> how will you add this in a way that prevents other authors in the future from doing (whatever people were worried about)? Just add comments saying "please don't use this unless X"?Precisely.My worry is that by introducing easy RW mmaped files in base is that it would make it easier to accidentally buy a class of very subtle bugs. Specifically I worry that people will:- start making RW files fly across the IPC boundary to co-share RW-MemoryMapped files with the browser and open the door to crash-on-truncate errors like explained above.- start blanket-replacing file I/O with rw-mmaps which looks easier and leaner to use but: (i) Introduces jank on aribtrary threads out of the control of todays's AllowedIO checks. (ii) increases the risk of crashes on corrupted filesystems. read()/write() on a corrupted fs returns an error. mmap() on a corrupted fs causes the entire process to crash (IIRC shess@ has seen this happening for real swithing sqlite from raw IO to mmap)
There must already exist a thousand ways inside Chrome to introduce jank
and other subtle usability issues.
This one, at least, is fairly obvious. It's also limited because it's not like the system is going to allocate objects in that memory that would then get used arbitrarily.
Also, it is reads (the existing functionality) that are the issue because of page-faults. The writing thread won't be impacted because the system flushes those to disk on its own time.
On Tue, Mar 8, 2016 at 2:00 PM Brian White <bcw...@google.com> wrote:There must already exist a thousand ways inside Chrome to introduce jankand other subtle usability issues.This is typically not a good reason for adding a new one. there are entire teams which work on multi year projects to reduce jank.
This one, at least, is fairly obvious. It's also limited because it's not like the system is going to allocate objects in that memory that would then get used arbitrarily.With the exception of:- vm readahead [1], that will pull in pages you never requested (on top of the standard I/O read-ahead mechanisms of the block layer), which might be beneficial or a waste of (clean) memory depending on your memory access patterns (in which case you are advised to use madvise(), but now how do you factor that in?).
- writeback that might cause higher peaks than direct write()'s, as dirty memory gets stashes until you hit the expiration timeout or exceed the dirty_ratio [2] threshold, or reach a memory pressure situation.
Also, it is reads (the existing functionality) that are the issue because of page-faults. The writing thread won't be impacted because the system flushes those to disk on its own time.Until you do the last write which exceeds the dirty_ratio/dirty_bytes threshold, in which case you now just caused your thread to be blocked on the entire writeback [3], which according to [4] mentions "For less than 1s think time (ext3/4 may block the dirtier for up to 800ms from time to time on 1-HDD)"
Yet again, I am not saying we shouldn't use mmaped memory. There have been cases, like the aforementioned shess@ one (crbug.com/555578) where this is has been hugely beneficial.But, as you see from this thread, there are a lot of catches associated, and IMHO very easy to do more harm than good. This is my only reason why I'd like that to see that as a feature which is really discouraged unless you really have strong arguments for it.At very least, this seems to me more a ::subtle API.