| #!/usr/bin/env python3 | |
| # Copyright 2022 The ChromiumOS Authors | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| """Test and benchmark the Bootstrap module.""" | |
| import math | |
| import pickle | |
| import unittest | |
| from bootstrap import BootstrapFullFARHierarchy | |
| from experiment import Experiment | |
| import fpsutils | |
| import simulate_fpstudy | |
| class Test_Bootstrap(unittest.TestCase): | |
| def setUp(self): | |
| # VerifyUser VerifyFinger VerifySample EnrollUser EnrollFinger Decision | |
| # This can take about 2 seconds. | |
| self.far_decisions = simulate_fpstudy.GenerateFARResults( | |
| num_users=72, | |
| num_fingers=3, | |
| num_verify_samples=40, | |
| user_groups=None, | |
| verbose=True, | |
| ) | |
| self.exp = Experiment( | |
| num_users=72, | |
| num_fingers=3, | |
| num_verification=40, | |
| far_decisions=self.far_decisions, | |
| ) | |
| def test_benchmark(self): | |
| """Test how long it takes to run the sampling using different modes.""" | |
| boot = BootstrapFullFARHierarchy(self.exp, verbose=True) | |
| boot.USE_GLOBAL_SHARING = True | |
| boot.run(num_samples=5000, num_proc=0) | |
| def test_benchmark_pickling(self): | |
| """Test how long it takes to pickle the Bootstrap object. | |
| Pickling can impact the performance of multiprocessing very heavily. | |
| Pickling could span between nanoseconds to seconds (or longer), | |
| depending on what data is contained in the object. | |
| Note that using `Bootstrap.USE_GLOBAL_SHARING` can avoid the high | |
| cost of pickling. | |
| Run this benchmark on your new Bootstrap sample to ensure that the | |
| bootstrap sample object is reasonably size. | |
| """ | |
| HYPOTHETICAL_NUM_CORES = [4, 64, 128] | |
| HYPOTHETICAL_NUM_SAMPLES = [5000, 10000, 100000] | |
| boot = BootstrapFullFARHierarchy(self.exp) | |
| fpsutils.benchmark( | |
| "vals = pickle.loads(pickle.dumps(123456))", | |
| globals={**locals(), **globals()}, | |
| ) | |
| _, _, pkl_time = fpsutils.benchmark( | |
| "pickle.dumps(boot)", globals={**locals(), **globals()} | |
| ) | |
| pkl_data = pickle.dumps(boot) | |
| _, _, unpkl_time = fpsutils.benchmark( | |
| "pickle.loads(pkl_data)", globals={**locals(), **globals()} | |
| ) | |
| print( | |
| f"Total pickling time is {fpsutils.elapsed_time_str(pkl_time + unpkl_time)}." | |
| ) | |
| for c in HYPOTHETICAL_NUM_CORES: | |
| for s in HYPOTHETICAL_NUM_SAMPLES: | |
| eta_calc = pkl_time + ( | |
| unpkl_time * math.ceil(float(s) / float(c)) | |
| ) | |
| eta = fpsutils.elapsed_time_str(eta_calc) | |
| print( | |
| f"Processing {s} samples running over {c},", | |
| f"could take {eta} in pickling.", | |
| ) | |
| print( | |
| "In reality, there is some other mechanism that seems " | |
| "to increase runtime with increasing number of processes, when " | |
| "the map interable objects are large." | |
| ) | |
| if __name__ == "__main__": | |
| unittest.main() |