Boost C++ Libraries: Ticket #9019: Bug: mapped_region shouldn't create a new file mapping but reuse the one provided in file_mapping https://svn.boost.org/trac10/ticket/9019 <p> In the constructor of the mapped_region class there is the following code: </p> <pre class="wiki">native_mapping_handle = winapi::create_file_mapping ( ipcdetail::file_handle_from_mapping_handle(mapping.get_mapping_handle()) , protection, 0, 0, 0); </pre><p> followed by the following: </p> <pre class="wiki">void *base = winapi::map_view_of_file_ex (native_mapping_handle, map_access, offset - page_offset, static_cast&lt;std::size_t&gt;(page_offset + size), const_cast&lt;void*&gt;(address)); </pre><p> Each invocation of the mapped_region's class constructor creates a new mapping. I think the code that creates the file mapping should be moved to the file_mapping class, so multiple mapped_regions could reuse the same file mapping. Currently, even if the same file_mapping instance is passed to the mapped_region's constructor, the file mapping isn't reused which makes creating multiple mapped regions of the same file slow. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/9019 Trac 1.4.3 Ion Gaztañaga Tue, 20 Aug 2013 17:30:38 GMT <link>https://svn.boost.org/trac10/ticket/9019#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9019#comment:1</guid> <description> <p> Calling <a class="missing wiki">CreateFileMapping</a> in the file_mapping class is not a trivial task as the size of the file can change and the file mapping would need to be recreated on the fly. Also, it wouldn't allow the same file using copy on write as the file mapping must be opened with an special flag for that purpose, whereas another view would like to write directly to the file. Do you have any performance numbers about the overhead of not reusing the file mapping? All portable shared memory interfaces I know create new file mappings when mapping the memory so I guess the performance impact is not very high. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Tue, 20 Aug 2013 17:36:29 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9019#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9019#comment:2</guid> <description> <p> Just as additional information, I've found: </p> <p> <a class="ext-link" href="http://www.labri.fr/perso/betrema/winnt/manamemo.html"><span class="icon">​</span>http://www.labri.fr/perso/betrema/winnt/manamemo.html</a> </p> <p> "To use a memory-mapped file, you start by creating a memory-mapped file object. The act of creating an MMF object has very little impact on system resources. It does not affect your process's address space, and no virtual memory is allocated for the object (other than for the internal resources that are necessary in representing the object)." </p> <p> Maybe it has no big impact in system resources but it could be much slower than reusing the object. </p> </description> <category>Ticket</category> </item> <item> <author>michal.fronczyk@…</author> <pubDate>Tue, 20 Aug 2013 21:55:41 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9019#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9019#comment:3</guid> <description> <p> Thanks for such a quick response. I think the problem is not about the time needed to create file mapping, but about the lack of ability to reuse already fetched pages of the file in different mapped regions. The performance problem we observed occurred in a multithreaded program. Using a profiler we discovered that the problem lies in the code where many threads were creating read-only mapped_regions of the same file using a shared instance of the file_mapping class. Different threads mapped different regions of the file, but there was a very high probability that a thread will shortly need the data region mapped previously by one of the other threads. I'm assuming that the destructor of the mapped_region class releases the mapping, so all the pages fetched during using that region are released when the region is destroyed and need to be fetched again from the disk when another region maps the same part of the file. Fetching the same parts of the file many times hurts the performance in our case. </p> <p> We changed the code to create one shared read-only mapped_region that maps the whole file and we use pointer arithmetic to read different parts of the file in different threads. The performance gain we observed was significant, but I don't have the numbers now. However, this solution isn't ideal because we can't do that in the 32bit version of the app since the file is big (several GBs). We map the whole file in the 64bit version only. BTW, do you see any problems with mapping a 20GB file as a whole to the 64bit address space? </p> <p> My thinking is that keeping the file_mapping instance and reusing it in multiple mapped_regions, that map small portions of the file, will allow us to reuse the fetched file pages in different mapped_regions as needed and the performance will be more or less the same as in the case of one shared mapped_region that maps the whole file. Please let me know if I'm wrong. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Wed, 21 Aug 2013 09:35:42 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9019#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9019#comment:4</guid> <description> <p> I think all file mappings share the same cached pages as coherency must be maintained: </p> <p> <a class="ext-link" href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366763(v=vs.85).aspx"><span class="icon">​</span>http://msdn.microsoft.com/en-us/library/windows/desktop/aa366763(v=vs.85).aspx</a> </p> <p> "With one important exception, file views derived from any file mapping object that is backed by the same file are coherent or identical at a specific time. Coherency is guaranteed for views within a process and for views that are mapped by different processes." </p> <p> (The exception is network files) </p> <p> I don't think the issue is related to destroying the file mapping (in fact the file mapping is destroyed just after mapping the memory with <a class="missing wiki">MapViewOfFile</a>), but because the mapped_region is unmapped (<a class="missing wiki">UnmapViewOfFile</a>). The OS knows that no other thread is mapping those pages so it could think it's a good opportunity to release them (although if there is enough file cache, it should be still there). I'm not sure how this can be fixed as it's quite OS dependent. </p> <p> Mapping the whole file shouldn't be a problem, at least in windows, as physical memory committed when the page is read (although I guess Windows will prefetch some pages). </p> </description> <category>Ticket</category> </item> <item> <author>michal.fronczyk@…</author> <pubDate>Fri, 23 Aug 2013 13:10:54 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9019#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9019#comment:5</guid> <description> <p> Thanks for explanation. You're probably right - this can't be fixed in an OS independent way. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Fri, 13 Sep 2013 20:29:38 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/9019#comment:6 https://svn.boost.org/trac10/ticket/9019#comment:6 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> I'm closing this as it does not seem there is a solution for it. Please reopen it if you have more information to improve the situation. Thanks for the report. </p> Ticket