<div dir="ltr">Sending pages to page server is the longest part of predump iteration and only here(and short time between criu dumps in p.haul) checkpointed program is not freezed so I think that&#39;s all we have.<br><br>To estimate: Walking one time across 0,5Gb of pages takes aproximately ~0.01 sec; on 10 Gbit/sec network the transfer time will be ~ 0.4 sec. So we will have approximately 3 such measurements. On my node for local transfer I got &gt;= 10 measurements in test: &quot;test/zdtm.py run --page-server --pre 1 -k always -t zdtm/static/maps04&quot;.<br></div><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature"><div dir="ltr"><br>Best Regards, Tikhomirov Pavel.</div></div></div>
<br><div class="gmail_quote">2016-04-12 14:12 GMT+03:00 Pavel Emelyanov <span dir="ltr">&lt;<a href="mailto:xemul@virtuozzo.com" target="_blank">xemul@virtuozzo.com</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On 04/07/2016 04:28 PM, Pavel Tikhomirov wrote:<br>
&gt; On memory predumping target process is unfreezed so it can change<br>
&gt; its memory, criu uses kernel soft-dirty tracking mechanism to find<br>
&gt; regions of unchanged memory and can skip dumping unchanged pages<br>
&gt; in iterative migration. Introduce dirty_logger_pthread to get<br>
&gt; number of dirty memory pages and all pages. Thus we will be<br>
&gt; able to analize memory iterative migration flow.<br>
&gt;<br>
&gt; move free_pstree to the end of cr_pre_dump_finish as will need it in<br>
&gt; dirty_logger_pthread<br>
&gt;<br>
&gt; Signed-off-by: Pavel Tikhomirov &lt;<a href="mailto:ptikhomirov@virtuozzo.com">ptikhomirov@virtuozzo.com</a>&gt;<br>
&gt; ---<br>
&gt;  criu/Makefile.crtools       |  1 +<br>
&gt;  criu/cr-dump.c              | 36 +++++++++++++++++++++++++++++++++++-<br>
&gt;  criu/dirty-logger.c         |  6 ++++++<br>
&gt;  criu/include/dirty-logger.h |  6 ++++++<br>
&gt;  4 files changed, 48 insertions(+), 1 deletion(-)<br>
&gt;  create mode 100644 criu/dirty-logger.c<br>
&gt;  create mode 100644 criu/include/dirty-logger.h<br>
&gt;<br>
&gt; diff --git a/criu/Makefile.crtools b/criu/Makefile.crtools<br>
&gt; index ef152d2..666a906 100644<br>
&gt; --- a/criu/Makefile.crtools<br>
&gt; +++ b/criu/Makefile.crtools<br>
&gt; @@ -13,6 +13,7 @@ obj-y                       += cr-exec.o<br>
&gt;  obj-y                        += cr-restore.o<br>
&gt;  obj-y                        += cr-service.o<br>
&gt;  obj-y                        += crtools.o<br>
&gt; +obj-y                        += dirty-logger.o<br>
&gt;  obj-y                        += eventfd.o<br>
&gt;  obj-y                        += eventpoll.o<br>
&gt;  obj-y                        += fault-injection.o<br>
&gt; diff --git a/criu/cr-dump.c b/criu/cr-dump.c<br>
&gt; index ade2f31..f188c1e 100644<br>
&gt; --- a/criu/cr-dump.c<br>
&gt; +++ b/criu/cr-dump.c<br>
&gt; @@ -22,6 +22,8 @@<br>
&gt;  #include &lt;sched.h&gt;<br>
&gt;  #include &lt;sys/resource.h&gt;<br>
&gt;<br>
&gt; +#include &lt;pthread.h&gt;<br>
&gt; +<br>
&gt;  #include &quot;protobuf.h&quot;<br>
&gt;  #include &quot;images/fdinfo.pb-c.h&quot;<br>
&gt;  #include &quot;images/fs.pb-c.h&quot;<br>
&gt; @@ -80,6 +82,7 @@<br>
&gt;  #include &quot;seccomp.h&quot;<br>
&gt;  #include &quot;seize.h&quot;<br>
&gt;  #include &quot;fault-injection.h&quot;<br>
&gt; +#include &quot;dirty-logger.h&quot;<br>
&gt;<br>
&gt;  #include &quot;asm/dump.h&quot;<br>
&gt;<br>
&gt; @@ -1426,15 +1429,25 @@ static int setup_alarm_handler()<br>
&gt;  static int cr_pre_dump_finish(struct list_head *ctls, int ret)<br>
&gt;  {<br>
&gt;       struct parasite_ctl *ctl, *n;<br>
&gt; +     pthread_t dirty_logger;<br>
&gt; +     int pthread_ret, arg = 0;<br>
&gt;<br>
&gt;       pstree_switch_state(root_item, TASK_ALIVE);<br>
&gt; -     free_pstree(root_item);<br>
&gt;<br>
&gt;       timing_stop(TIME_FROZEN);<br>
&gt;<br>
&gt;       if (ret &lt; 0)<br>
&gt;               goto err;<br>
&gt;<br>
&gt; +     if (opts.log_dirty) {<br>
&gt; +             pr_info(&quot;Start dirty memory logger on pre-dumping tasks&#39; memory\n&quot;);<br>
&gt; +             pthread_ret = pthread_create(&amp;dirty_logger, NULL, dirty_logger_pthread, (void *)&amp;arg);<br>
&gt; +             if (pthread_ret) {<br>
&gt; +                     pr_err(&quot;Pthread creation of dirty_logger_pthread failed: %d\n&quot;, pthread_ret);<br>
&gt; +                     return -1;<br>
&gt; +             }<br>
&gt; +     }<br>
&gt; +<br>
&gt;       pr_info(&quot;Pre-dumping tasks&#39; memory\n&quot;);<br>
&gt;       list_for_each_entry_safe(ctl, n, ctls, pre_list) {<br>
&gt;               struct page_xfer xfer;<br>
&gt; @@ -1477,6 +1490,27 @@ static int cr_pre_dump_finish(struct list_head *ctls, int ret)<br>
&gt;               write_stats(DUMP_STATS);<br>
&gt;               pr_info(&quot;Pre-dumping finished successfully\n&quot;);<br>
&gt;       }<br>
&gt; +<br>
&gt; +     if (opts.log_dirty) {<br>
&gt; +             pr_info(&quot;Stop dirty memory logger\n&quot;);<br>
&gt; +             pthread_ret = pthread_cancel(dirty_logger);<br>
&gt; +             if (pthread_ret &amp;&amp; pthread_ret != ESRCH) {<br>
&gt; +                     pr_err(&quot;Pthread cancel of dirty_logger_pthread failed: %d\n&quot;, pthread_ret);<br>
&gt; +                     ret = -1;<br>
&gt; +                     goto exit;<br>
&gt; +             }<br>
&gt; +             pthread_ret = pthread_join(dirty_logger, NULL);<br>
&gt; +             if (pthread_ret) {<br>
&gt; +                     pr_perror(&quot;Pthread join of dirty_logger_pthread failed: %d\n&quot;, pthread_ret);<br>
&gt; +                     ret = -1;<br>
&gt; +                     goto exit;<br>
&gt; +             }<br>
&gt; +             if (arg == -1)<br>
&gt; +                     pr_perror(&quot;Pthread dirty_logger_pthread failed\n&quot;);<br>
<br>
</div></div>You kill this thread right after pre-dump finish, so this thread only works when<br>
the pre-dump is in action. This is quite short period of time, is it enough?<br>
<div class="HOEnZb"><div class="h5"><br>
&gt; +     }<br>
&gt; +<br>
&gt; +exit:<br>
&gt; +     free_pstree(root_item);<br>
&gt;       return ret;<br>
&gt;  }<br>
&gt;<br>
&gt; diff --git a/criu/dirty-logger.c b/criu/dirty-logger.c<br>
&gt; new file mode 100644<br>
&gt; index 0000000..6620626<br>
&gt; --- /dev/null<br>
&gt; +++ b/criu/dirty-logger.c<br>
&gt; @@ -0,0 +1,6 @@<br>
&gt; +#include &lt;pthread.h&gt;<br>
&gt; +<br>
&gt; +void *dirty_logger_pthread(void *arg)<br>
&gt; +{<br>
&gt; +     pthread_exit(NULL);<br>
&gt; +}<br>
&gt; diff --git a/criu/include/dirty-logger.h b/criu/include/dirty-logger.h<br>
&gt; new file mode 100644<br>
&gt; index 0000000..312c44b<br>
&gt; --- /dev/null<br>
&gt; +++ b/criu/include/dirty-logger.h<br>
&gt; @@ -0,0 +1,6 @@<br>
&gt; +#ifndef __CR_DIRTY_LOGGER_H__<br>
&gt; +#define __CR_DIRTY_LOGGER_H__<br>
&gt; +<br>
&gt; +extern void *dirty_logger_pthread(void *arg);<br>
&gt; +<br>
&gt; +#endif<br>
&gt;<br>
<br>
</div></div><div class="HOEnZb"><div class="h5">_______________________________________________<br>
CRIU mailing list<br>
<a href="mailto:CRIU@openvz.org">CRIU@openvz.org</a><br>
<a href="https://lists.openvz.org/mailman/listinfo/criu" rel="noreferrer" target="_blank">https://lists.openvz.org/mailman/listinfo/criu</a><br>
</div></div></blockquote></div><br></div>