1 //  Copyright (c) 2015 Hartmut Kaiser
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <hpx/hpx_main.hpp>
7 #include <hpx/include/components.hpp>
8 #include <hpx/include/actions.hpp>
9 #include <hpx/util/lightweight_test.hpp>
10 
11 #include <cstddef>
12 #include <cstdint>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 
17 ///////////////////////////////////////////////////////////////////////////////
18 struct test_server : hpx::components::simple_component_base<test_server>
19 {
calltest_server20     hpx::id_type call() const { return hpx::find_here(); }
21 
22     HPX_DEFINE_COMPONENT_ACTION(test_server, call);
23 };
24 
25 typedef hpx::components::simple_component<test_server> server_type;
26 HPX_REGISTER_COMPONENT(server_type, test_server);
27 
28 typedef test_server::call_action call_action;
29 HPX_REGISTER_ACTION(call_action);
30 
31 struct test_client : hpx::components::client_base<test_client, test_server>
32 {
33     typedef hpx::components::client_base<test_client, test_server> base_type;
34 
test_clienttest_client35     test_client(hpx::future<hpx::id_type>&& id)
36       : base_type(std::move(id))
37     {}
test_clienttest_client38     test_client(hpx::id_type&& id)
39       : base_type(std::move(id))
40     {}
41 
calltest_client42     hpx::id_type  call()
43     {
44         return hpx::async<call_action>(this->get_id()).get();
45     }
46 };
47 
48 ///////////////////////////////////////////////////////////////////////////////
test_binpacking_multiple()49 std::vector<hpx::id_type> test_binpacking_multiple()
50 {
51     std::vector<hpx::id_type> keep_alive;
52 
53     // create an increasing number of instances on all available localities
54     std::vector<std::vector<hpx::id_type> > targets;
55 
56     std::vector<hpx::id_type> localities = hpx::find_all_localities();
57 
58     for (std::size_t i = 0; i != localities.size(); ++i)
59     {
60         hpx::id_type const& loc = localities[i];
61 
62         targets.push_back(hpx::new_<test_server[]>(loc, i + 1).get());
63         for (hpx::id_type const& id: targets.back())
64         {
65             HPX_TEST(hpx::async<call_action>(id).get() == loc);
66             keep_alive.push_back(id);
67         }
68     }
69 
70     std::string counter_name(hpx::components::default_binpacking_counter_name);
71     counter_name += "test_server";
72 
73     std::uint64_t count = 0;
74     for (std::size_t i = 0; i != localities.size(); ++i)
75     {
76         hpx::performance_counters::performance_counter instances(
77             counter_name, localities[i]);
78 
79         std::uint64_t c = instances.get_value<std::uint64_t>(hpx::launch::sync);
80         count += c;
81         HPX_TEST_EQ(c, i + 1);
82     }
83 
84     HPX_TEST_EQ(count, keep_alive.size());
85 
86     // now use bin-packing policy to fill up the number of instances
87     std::vector<hpx::id_type> filled_targets =
88         hpx::new_<test_server[]>(hpx::binpacked(localities), count).get();
89 
90     // now, all localities should have the same number of instances
91     std::uint64_t new_count = 0;
92     for (std::size_t i = 0; i != localities.size(); ++i)
93     {
94         hpx::performance_counters::performance_counter instances(
95             counter_name, localities[i]);
96 
97         std::uint64_t c =
98             instances.get_value<std::uint64_t>(hpx::launch::sync);
99         new_count += c;
100         HPX_TEST_EQ(c, localities.size() + 1);
101     }
102 
103     HPX_TEST_EQ(2*count, new_count);
104 
105     for (hpx::id_type const& id: filled_targets)
106         keep_alive.push_back(id);
107 
108     return keep_alive;
109 }
110 
111 ///////////////////////////////////////////////////////////////////////////////
test_binpacking_single()112 void test_binpacking_single()
113 {
114     // create an increasing number of instances on all available localities
115     std::vector<std::vector<hpx::id_type> > targets;
116 
117     std::vector<hpx::id_type> localities = hpx::find_all_localities();
118     for (std::size_t i = 0; i != localities.size(); ++i)
119     {
120         hpx::id_type const& loc = localities[i];
121 
122         targets.push_back(hpx::new_<test_server[]>(loc, i+1).get());
123         for (hpx::id_type const& id: targets.back())
124         {
125             HPX_TEST(hpx::async<call_action>(id).get() == loc);
126         }
127     }
128 
129     std::string counter_name(hpx::components::default_binpacking_counter_name);
130     counter_name += "test_server";
131 
132     hpx::performance_counters::performance_counter instances(
133         counter_name, localities[0]);
134     std::uint64_t before =
135         instances.get_value<std::uint64_t>(hpx::launch::sync);
136 
137     // now use bin-packing policy to create one more instance
138     hpx::id_type filled_target = hpx::new_<test_server>(
139         hpx::binpacked(localities)).get();
140 
141     // now, the first locality should have one more instance
142     std::uint64_t after =
143         instances.get_value<std::uint64_t>(hpx::launch::sync);
144 
145     HPX_TEST_EQ(before+1, after);
146 }
147 
main()148 int main()
149 {
150     std::vector<hpx::id_type> ids = test_binpacking_multiple();
151     test_binpacking_single();
152 
153     return hpx::util::report_errors();
154 }
155 
156