added test to measure peak download rate and introduced performance warning alert when disk buffer limit and request limit are reached

This commit is contained in:
Arvid Norberg
2008-08-19 15:04:14 +00:00
parent a134908bac
commit 37389e4fe4
8 changed files with 219 additions and 56 deletions

View File

@@ -167,65 +167,66 @@
<li><a class="reference" href="#peer-error-alert" id="id144" name="id144">peer_error_alert</a></li> <li><a class="reference" href="#peer-error-alert" id="id144" name="id144">peer_error_alert</a></li>
<li><a class="reference" href="#invalid-request-alert" id="id145" name="id145">invalid_request_alert</a></li> <li><a class="reference" href="#invalid-request-alert" id="id145" name="id145">invalid_request_alert</a></li>
<li><a class="reference" href="#torrent-finished-alert" id="id146" name="id146">torrent_finished_alert</a></li> <li><a class="reference" href="#torrent-finished-alert" id="id146" name="id146">torrent_finished_alert</a></li>
<li><a class="reference" href="#metadata-failed-alert" id="id147" name="id147">metadata_failed_alert</a></li> <li><a class="reference" href="#performance-alert" id="id147" name="id147">performance_alert</a></li>
<li><a class="reference" href="#metadata-received-alert" id="id148" name="id148">metadata_received_alert</a></li> <li><a class="reference" href="#metadata-failed-alert" id="id148" name="id148">metadata_failed_alert</a></li>
<li><a class="reference" href="#fastresume-rejected-alert" id="id149" name="id149">fastresume_rejected_alert</a></li> <li><a class="reference" href="#metadata-received-alert" id="id149" name="id149">metadata_received_alert</a></li>
<li><a class="reference" href="#peer-blocked-alert" id="id150" name="id150">peer_blocked_alert</a></li> <li><a class="reference" href="#fastresume-rejected-alert" id="id150" name="id150">fastresume_rejected_alert</a></li>
<li><a class="reference" href="#storage-moved-alert" id="id151" name="id151">storage_moved_alert</a></li> <li><a class="reference" href="#peer-blocked-alert" id="id151" name="id151">peer_blocked_alert</a></li>
<li><a class="reference" href="#torrent-paused-alert" id="id152" name="id152">torrent_paused_alert</a></li> <li><a class="reference" href="#storage-moved-alert" id="id152" name="id152">storage_moved_alert</a></li>
<li><a class="reference" href="#torrent-resumed-alert" id="id153" name="id153">torrent_resumed_alert</a></li> <li><a class="reference" href="#torrent-paused-alert" id="id153" name="id153">torrent_paused_alert</a></li>
<li><a class="reference" href="#save-resume-data-alert" id="id154" name="id154">save_resume_data_alert</a></li> <li><a class="reference" href="#torrent-resumed-alert" id="id154" name="id154">torrent_resumed_alert</a></li>
<li><a class="reference" href="#save-resume-data-failed-alert" id="id155" name="id155">save_resume_data_failed_alert</a></li> <li><a class="reference" href="#save-resume-data-alert" id="id155" name="id155">save_resume_data_alert</a></li>
<li><a class="reference" href="#dispatcher" id="id156" name="id156">dispatcher</a></li> <li><a class="reference" href="#save-resume-data-failed-alert" id="id156" name="id156">save_resume_data_failed_alert</a></li>
<li><a class="reference" href="#dispatcher" id="id157" name="id157">dispatcher</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#exceptions" id="id157" name="id157">exceptions</a><ul> <li><a class="reference" href="#exceptions" id="id158" name="id158">exceptions</a><ul>
<li><a class="reference" href="#invalid-handle" id="id158" name="id158">invalid_handle</a></li> <li><a class="reference" href="#invalid-handle" id="id159" name="id159">invalid_handle</a></li>
<li><a class="reference" href="#duplicate-torrent" id="id159" name="id159">duplicate_torrent</a></li> <li><a class="reference" href="#duplicate-torrent" id="id160" name="id160">duplicate_torrent</a></li>
<li><a class="reference" href="#invalid-encoding" id="id160" name="id160">invalid_encoding</a></li> <li><a class="reference" href="#invalid-encoding" id="id161" name="id161">invalid_encoding</a></li>
<li><a class="reference" href="#type-error" id="id161" name="id161">type_error</a></li> <li><a class="reference" href="#type-error" id="id162" name="id162">type_error</a></li>
<li><a class="reference" href="#invalid-torrent-file" id="id162" name="id162">invalid_torrent_file</a></li> <li><a class="reference" href="#invalid-torrent-file" id="id163" name="id163">invalid_torrent_file</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#storage-interface" id="id163" name="id163">storage_interface</a><ul> <li><a class="reference" href="#storage-interface" id="id164" name="id164">storage_interface</a><ul>
<li><a class="reference" href="#initialize" id="id164" name="id164">initialize()</a></li> <li><a class="reference" href="#initialize" id="id165" name="id165">initialize()</a></li>
<li><a class="reference" href="#read" id="id165" name="id165">read()</a></li> <li><a class="reference" href="#read" id="id166" name="id166">read()</a></li>
<li><a class="reference" href="#write" id="id166" name="id166">write()</a></li> <li><a class="reference" href="#write" id="id167" name="id167">write()</a></li>
<li><a class="reference" href="#id12" id="id167" name="id167">move_storage()</a></li> <li><a class="reference" href="#id12" id="id168" name="id168">move_storage()</a></li>
<li><a class="reference" href="#verify-resume-data" id="id168" name="id168">verify_resume_data()</a></li> <li><a class="reference" href="#verify-resume-data" id="id169" name="id169">verify_resume_data()</a></li>
<li><a class="reference" href="#write-resume-data" id="id169" name="id169">write_resume_data()</a></li> <li><a class="reference" href="#write-resume-data" id="id170" name="id170">write_resume_data()</a></li>
<li><a class="reference" href="#move-slot" id="id170" name="id170">move_slot()</a></li> <li><a class="reference" href="#move-slot" id="id171" name="id171">move_slot()</a></li>
<li><a class="reference" href="#swap-slots" id="id171" name="id171">swap_slots()</a></li> <li><a class="reference" href="#swap-slots" id="id172" name="id172">swap_slots()</a></li>
<li><a class="reference" href="#swap-slots3" id="id172" name="id172">swap_slots3()</a></li> <li><a class="reference" href="#swap-slots3" id="id173" name="id173">swap_slots3()</a></li>
<li><a class="reference" href="#hash-for-slot" id="id173" name="id173">hash_for_slot()</a></li> <li><a class="reference" href="#hash-for-slot" id="id174" name="id174">hash_for_slot()</a></li>
<li><a class="reference" href="#release-files" id="id174" name="id174">release_files()</a></li> <li><a class="reference" href="#release-files" id="id175" name="id175">release_files()</a></li>
<li><a class="reference" href="#delete-files" id="id175" name="id175">delete_files()</a></li> <li><a class="reference" href="#delete-files" id="id176" name="id176">delete_files()</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#magnet-links" id="id176" name="id176">magnet links</a></li> <li><a class="reference" href="#magnet-links" id="id177" name="id177">magnet links</a></li>
<li><a class="reference" href="#queuing" id="id177" name="id177">queuing</a><ul> <li><a class="reference" href="#queuing" id="id178" name="id178">queuing</a><ul>
<li><a class="reference" href="#downloading" id="id178" name="id178">downloading</a></li> <li><a class="reference" href="#downloading" id="id179" name="id179">downloading</a></li>
<li><a class="reference" href="#seeding" id="id179" name="id179">seeding</a></li> <li><a class="reference" href="#seeding" id="id180" name="id180">seeding</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#fast-resume" id="id180" name="id180">fast resume</a><ul> <li><a class="reference" href="#fast-resume" id="id181" name="id181">fast resume</a><ul>
<li><a class="reference" href="#file-format" id="id181" name="id181">file format</a></li> <li><a class="reference" href="#file-format" id="id182" name="id182">file format</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#threads" id="id182" name="id182">threads</a></li> <li><a class="reference" href="#threads" id="id183" name="id183">threads</a></li>
<li><a class="reference" href="#storage-allocation" id="id183" name="id183">storage allocation</a><ul> <li><a class="reference" href="#storage-allocation" id="id184" name="id184">storage allocation</a><ul>
<li><a class="reference" href="#sparse-allocation" id="id184" name="id184">sparse allocation</a></li> <li><a class="reference" href="#sparse-allocation" id="id185" name="id185">sparse allocation</a></li>
<li><a class="reference" href="#full-allocation" id="id185" name="id185">full allocation</a></li> <li><a class="reference" href="#full-allocation" id="id186" name="id186">full allocation</a></li>
<li><a class="reference" href="#compact-allocation" id="id186" name="id186">compact allocation</a></li> <li><a class="reference" href="#compact-allocation" id="id187" name="id187">compact allocation</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#extensions" id="id187" name="id187">extensions</a><ul> <li><a class="reference" href="#extensions" id="id188" name="id188">extensions</a><ul>
<li><a class="reference" href="#metadata-from-peers" id="id188" name="id188">metadata from peers</a></li> <li><a class="reference" href="#metadata-from-peers" id="id189" name="id189">metadata from peers</a></li>
<li><a class="reference" href="#http-seeding" id="id189" name="id189">HTTP seeding</a></li> <li><a class="reference" href="#http-seeding" id="id190" name="id190">HTTP seeding</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#filename-checks" id="id190" name="id190">filename checks</a></li> <li><a class="reference" href="#filename-checks" id="id191" name="id191">filename checks</a></li>
<li><a class="reference" href="#acknowledgments" id="id191" name="id191">acknowledgments</a></li> <li><a class="reference" href="#acknowledgments" id="id192" name="id192">acknowledgments</a></li>
</ul> </ul>
</div> </div>
<div class="section"> <div class="section">
@@ -3717,6 +3718,10 @@ pieces are completed.</td>
<tr><td><tt class="docutils literal"><span class="pre">ip_block_notification</span></tt></td> <tr><td><tt class="docutils literal"><span class="pre">ip_block_notification</span></tt></td>
<td>Alerts when a peer is blocked by the ip blocker or port blocker.</td> <td>Alerts when a peer is blocked by the ip blocker or port blocker.</td>
</tr> </tr>
<tr><td><tt class="docutils literal"><span class="pre">performance_warning</span></tt></td>
<td>Alerts when some limit is reached that might limit the download
or upload rate.</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">all_categories</span></tt></td> <tr><td><tt class="docutils literal"><span class="pre">all_categories</span></tt></td>
<td>The full bitmask, representing all available categories.</td> <td>The full bitmask, representing all available categories.</td>
</tr> </tr>
@@ -3747,6 +3752,7 @@ public:
status_notification = <em>implementation defined</em>, status_notification = <em>implementation defined</em>,
progress_notification = <em>implementation defined</em>, progress_notification = <em>implementation defined</em>,
ip_block_notification = <em>implementation defined</em>, ip_block_notification = <em>implementation defined</em>,
performance_warning = <em>implementation defined</em>,
all_categories = <em>implementation defined</em> all_categories = <em>implementation defined</em>
}; };
@@ -4063,6 +4069,25 @@ torrent in question.</p>
<p>There are no additional data members in this alert.</p> <p>There are no additional data members in this alert.</p>
</div> </div>
<div class="section"> <div class="section">
<h2><a id="performance-alert" name="performance-alert">performance_alert</a></h2>
<p>This alert is generated when a limit is reached that might have a negative impact on
upload or download rate performance.</p>
<pre class="literal-block">
struct performance_alert: torrent_alert
{
// ...
enum performance_warning_t
{
outstanding_disk_buffer_limit_reached,
outstanding_request_limit_reached,
};
performance_warning_t warning_code;
};
</pre>
</div>
<div class="section">
<h2><a id="metadata-failed-alert" name="metadata-failed-alert">metadata_failed_alert</a></h2> <h2><a id="metadata-failed-alert" name="metadata-failed-alert">metadata_failed_alert</a></h2>
<p>This alert is generated when the metadata has been completely received and the info-hash <p>This alert is generated when the metadata has been completely received and the info-hash
failed to match it. i.e. the metadata that was received was corrupt. libtorrent will failed to match it. i.e. the metadata that was received was corrupt. libtorrent will

View File

@@ -3793,6 +3793,9 @@ is a bitmask with the following bits:
+--------------------------------+---------------------------------------------------------------------+ +--------------------------------+---------------------------------------------------------------------+
| ``ip_block_notification`` | Alerts when a peer is blocked by the ip blocker or port blocker. | | ``ip_block_notification`` | Alerts when a peer is blocked by the ip blocker or port blocker. |
+--------------------------------+---------------------------------------------------------------------+ +--------------------------------+---------------------------------------------------------------------+
| ``performance_warning`` | Alerts when some limit is reached that might limit the download |
| | or upload rate. |
+--------------------------------+---------------------------------------------------------------------+
| ``all_categories`` | The full bitmask, representing all available categories. | | ``all_categories`` | The full bitmask, representing all available categories. |
+--------------------------------+---------------------------------------------------------------------+ +--------------------------------+---------------------------------------------------------------------+
@@ -3826,6 +3829,7 @@ is its synopsis:
status_notification = *implementation defined*, status_notification = *implementation defined*,
progress_notification = *implementation defined*, progress_notification = *implementation defined*,
ip_block_notification = *implementation defined*, ip_block_notification = *implementation defined*,
performance_warning = *implementation defined*,
all_categories = *implementation defined* all_categories = *implementation defined*
}; };
@@ -4205,6 +4209,28 @@ torrent in question.
There are no additional data members in this alert. There are no additional data members in this alert.
performance_alert
-----------------
This alert is generated when a limit is reached that might have a negative impact on
upload or download rate performance.
::
struct performance_alert: torrent_alert
{
// ...
enum performance_warning_t
{
outstanding_disk_buffer_limit_reached,
outstanding_request_limit_reached,
};
performance_warning_t warning_code;
};
metadata_failed_alert metadata_failed_alert
--------------------- ---------------------

View File

@@ -82,6 +82,7 @@ namespace libtorrent {
status_notification = 0x40, status_notification = 0x40,
progress_notification = 0x80, progress_notification = 0x80,
ip_block_notification = 0x100, ip_block_notification = 0x100,
performance_warning = 0x200,
all_categories = 0xffffffff all_categories = 0xffffffff
}; };

View File

@@ -151,6 +151,42 @@ namespace libtorrent
int index; int index;
}; };
struct TORRENT_EXPORT performance_alert: torrent_alert
{
enum performance_warning_t
{
outstanding_disk_buffer_limit_reached,
outstanding_request_limit_reached,
};
performance_alert(torrent_handle const& h
, performance_warning_t w)
: torrent_alert(h)
, warning_code(w)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new performance_alert(*this)); }
virtual char const* what() const { return "performance warning"; }
virtual std::string message() const
{
static char const* warning_str[] =
{
"max outstanding disk writes reached",
"max outstanding piece requests reached",
};
return torrent_alert::message() + ": performance warning: "
+ warning_str[warning_code];
}
const static int static_category = alert::performance_warning;
virtual int category() const { return static_category; }
performance_warning_t warning_code;
};
struct TORRENT_EXPORT state_changed_alert: torrent_alert struct TORRENT_EXPORT state_changed_alert: torrent_alert
{ {
state_changed_alert(torrent_handle const& h state_changed_alert(torrent_handle const& h

View File

@@ -1643,6 +1643,13 @@ namespace libtorrent
TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle); TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle);
m_download_queue.erase(b); m_download_queue.erase(b);
if (m_outstanding_writing_bytes >= m_ses.settings().max_outstanding_disk_bytes_per_connection
&& t->alerts().should_post<performance_alert>())
{
t->alerts().post_alert(performance_alert(t->get_handle()
, performance_alert::outstanding_disk_buffer_limit_reached));
}
if (!m_download_queue.empty()) if (!m_download_queue.empty())
{ {
m_timeout_extend = (std::max)(m_timeout_extend m_timeout_extend = (std::max)(m_timeout_extend
@@ -2765,6 +2772,13 @@ namespace libtorrent
m_desired_queue_size = m_max_out_request_queue; m_desired_queue_size = m_max_out_request_queue;
if (m_desired_queue_size < min_request_queue) if (m_desired_queue_size < min_request_queue)
m_desired_queue_size = min_request_queue; m_desired_queue_size = min_request_queue;
if (m_desired_queue_size == m_max_out_request_queue
&& t->alerts().should_post<performance_alert>())
{
t->alerts().post_alert(performance_alert(t->get_handle()
, performance_alert::outstanding_request_limit_reached));
}
} }
if (!m_download_queue.empty() if (!m_download_queue.empty()

View File

@@ -196,14 +196,14 @@ boost::intrusive_ptr<T> clone_ptr(boost::intrusive_ptr<T> const& ptr)
return boost::intrusive_ptr<T>(new T(*ptr)); return boost::intrusive_ptr<T>(new T(*ptr));
} }
boost::intrusive_ptr<torrent_info> create_torrent(std::ostream* file, int piece_size) boost::intrusive_ptr<torrent_info> create_torrent(std::ostream* file, int piece_size, int num_pieces)
{ {
char const* tracker_url = "http://non-existent-name.com/announce"; char const* tracker_url = "http://non-existent-name.com/announce";
using namespace boost::filesystem; using namespace boost::filesystem;
file_storage fs; file_storage fs;
int total_size = 2 * 1024 * 1024; int total_size = piece_size * num_pieces;
fs.add_file(path("temporary"), total_size); fs.add_file(path("temporary"), total_size);
libtorrent::create_torrent t(fs, piece_size); libtorrent::create_torrent t(fs, piece_size);
t.add_tracker(tracker_url); t.add_tracker(tracker_url);
@@ -253,7 +253,7 @@ setup_transfer(session* ses1, session* ses2, session* ses3
{ {
create_directory("./tmp1" + suffix); create_directory("./tmp1" + suffix);
std::ofstream file(("./tmp1" + suffix + "/temporary").c_str()); std::ofstream file(("./tmp1" + suffix + "/temporary").c_str());
t = ::create_torrent(&file, piece_size); t = ::create_torrent(&file, piece_size, 1024 / 8);
file.close(); file.close();
if (clear_files) if (clear_files)
{ {

View File

@@ -42,7 +42,7 @@ void print_alerts(libtorrent::session& ses, char const* name
, bool allow_no_torrents = false); , bool allow_no_torrents = false);
void test_sleep(int millisec); void test_sleep(int millisec);
boost::intrusive_ptr<libtorrent::torrent_info> create_torrent(std::ostream* file = 0, int piece_size = 16 * 1024); boost::intrusive_ptr<libtorrent::torrent_info> create_torrent(std::ostream* file = 0, int piece_size = 16 * 1024, int num_pieces = 1024 / 8);
boost::tuple<libtorrent::torrent_handle, libtorrent::torrent_handle boost::tuple<libtorrent::torrent_handle, libtorrent::torrent_handle
, libtorrent::torrent_handle> , libtorrent::torrent_handle>

View File

@@ -45,12 +45,64 @@ POSSIBILITY OF SUCH DAMAGE.
using boost::filesystem::remove_all; using boost::filesystem::remove_all;
using boost::filesystem::exists; using boost::filesystem::exists;
using boost::filesystem::create_directory; using boost::filesystem::create_directory;
using namespace libtorrent;
using boost::tuples::ignore;
// test the maximum transfer rate
void test_rate()
{
session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48575, 49000));
session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49575, 50000));
torrent_handle tor1;
torrent_handle tor2;
create_directory("./tmp1_transfer");
std::ofstream file("./tmp1_transfer/temporary");
boost::intrusive_ptr<torrent_info> t = ::create_torrent(&file, 4 * 1024 * 1024, 50);
file.close();
boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, 0
, true, false, true, "_transfer", 0, &t);
ses1.set_alert_mask(alert::all_categories & ~alert::progress_notification);
ses2.set_alert_mask(alert::all_categories & ~alert::progress_notification);
ptime start = time_now();
for (int i = 0; i < 40; ++i)
{
print_alerts(ses1, "ses1");
print_alerts(ses2, "ses2");
torrent_status st1 = tor1.status();
torrent_status st2 = tor2.status();
std::cerr
<< "up: \033[33m" << st1.upload_payload_rate / 1000000.f << "MB/s "
<< " down: \033[32m" << st2.download_payload_rate / 1000000.f << "MB/s "
<< "\033[0m" << int(st2.progress * 100) << "% "
<< std::endl;
if (st1.paused) break;
if (tor2.is_seed()) break;
test_sleep(1000);
}
TEST_CHECK(tor2.is_seed());
time_duration dt = time_now() - start;
std::cerr << "downloaded " << t->total_size() << " bytes "
"in " << (total_milliseconds(dt) / 1000.f) << " seconds" << std::endl;
std::cerr << "average download rate: " << (t->total_size() / total_milliseconds(dt))
<< " kB/s" << std::endl;
}
void test_transfer() void test_transfer()
{ {
using namespace libtorrent;
using boost::tuples::ignore;
session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48075, 49000)); session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48075, 49000));
session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49075, 50000)); session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49075, 50000));
@@ -83,9 +135,6 @@ void test_transfer()
ses1.set_alert_mask(alert::all_categories & ~alert::progress_notification); ses1.set_alert_mask(alert::all_categories & ~alert::progress_notification);
ses2.set_alert_mask(alert::all_categories & ~alert::progress_notification); ses2.set_alert_mask(alert::all_categories & ~alert::progress_notification);
tor1.resume();
tor2.resume();
for (int i = 0; i < 30; ++i) for (int i = 0; i < 30; ++i)
{ {
print_alerts(ses1, "ses1"); print_alerts(ses1, "ses1");
@@ -158,6 +207,7 @@ void test_transfer()
p.save_path = "./tmp2_transfer"; p.save_path = "./tmp2_transfer";
p.resume_data = &resume_data; p.resume_data = &resume_data;
tor2 = ses2.add_torrent(p); tor2 = ses2.add_torrent(p);
ses2.set_alert_mask(alert::all_categories & ~alert::progress_notification);
tor2.prioritize_pieces(priorities); tor2.prioritize_pieces(priorities);
std::cout << "resetting priorities" << std::endl; std::cout << "resetting priorities" << std::endl;
tor2.resume(); tor2.resume();
@@ -224,8 +274,19 @@ int test_main()
try { remove_all("./tmp1_transfer"); } catch (std::exception&) {} try { remove_all("./tmp1_transfer"); } catch (std::exception&) {}
try { remove_all("./tmp2_transfer"); } catch (std::exception&) {} try { remove_all("./tmp2_transfer"); } catch (std::exception&) {}
#ifdef NDEBUG
// test rate only makes sense in release mode
test_rate();
try { remove_all("./tmp1_transfer"); } catch (std::exception&) {}
try { remove_all("./tmp2_transfer"); } catch (std::exception&) {}
#endif
test_transfer(); test_transfer();
try { remove_all("./tmp1_transfer"); } catch (std::exception&) {}
try { remove_all("./tmp2_transfer"); } catch (std::exception&) {}
return 0; return 0;
} }