Compare commits

..

No commits in common. "9a855daabfb21bf2601bdcfc22f68c106f93146e" and "c307783ef259962d21d440cf13360d18b308b26d" have entirely different histories.

8 changed files with 22 additions and 224 deletions

View File

@ -33,8 +33,7 @@ else()
endif() endif()
endif() endif()
target_link_libraries(QVectorSearch PRIVATE Qt${QT_VERSION_MAJOR}::Widgets target_link_libraries(QVectorSearch PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
vector_search)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. If # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. If
# you are developing for iOS or macOS you should consider setting an explicit, # you are developing for iOS or macOS you should consider setting an explicit,

View File

@ -1,95 +1,9 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "./ui_mainwindow.h" #include "./ui_mainwindow.h"
#include "finder.h"
#include "linear_finder.h"
#include "parallel_finder.h"
#include "timer.h"
#include "word_list_generator.h"
#include <thread>
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) { : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this); ui->setupUi(this);
ui->resultView->setModel(&result_model_);
ui->searchAlgorithmSelector->setModel(&search_algorithms_);
setupAlgorithmSelector();
generateWordList();
} }
MainWindow::~MainWindow() { delete ui; } MainWindow::~MainWindow() { delete ui; }
void MainWindow::setupAlgorithmSelector() {
search_algorithms_.appendRow(new QStandardItem("Linear search"));
search_algorithms_.appendRow(new QStandardItem("Parallel search"));
}
void MainWindow::generateWordList() {
Timer timer;
word_list_ = WordListGenerator().generate();
timer.stop();
std::stringstream status_message;
status_message << "generated " << word_list_.size() << " words in " << timer;
ui->mainStatusBar->showMessage(QString::fromStdString(status_message.str()));
QStringList words;
for (auto word : word_list_) {
words.append(QString::fromStdString(word));
}
result_model_.setStringList(words);
}
void MainWindow::search(const QString &search_term) {
if (search_term.isEmpty()) {
result_model_.setStringList(QStringList());
ui->mainStatusBar->clearMessage();
return;
}
Timer timer;
const auto finder = createSelectedFinder();
const auto results = finder->find_prefix(search_term.toStdString());
timer.stop();
std::stringstream status_message;
status_message << "search took " << timer << ", found " << results.size()
<< " results";
ui->mainStatusBar->showMessage(QString::fromStdString(status_message.str()));
showResults(results);
}
std::unique_ptr<Finder> MainWindow::createSelectedFinder() const {
auto selectedFinder = ui->searchAlgorithmSelector->currentIndex();
switch (selectedFinder) {
case 0:
default:
return std::make_unique<LinearFinder>(word_list_);
case 1:
return std::make_unique<ParallelFinder>(
word_list_, std::thread::hardware_concurrency());
}
}
void MainWindow::showResults(const std::vector<const std::string *> &results) {
QStringList ui_results;
for (auto word : results) {
ui_results.append(QString::fromStdString(*word));
}
result_model_.setStringList(ui_results);
}
void MainWindow::on_searchInput_textChanged(const QString &search_term) {
search(search_term);
}
void MainWindow::on_searchAlgorithmSelector_currentIndexChanged(int) {
search(ui->searchInput->displayText());
}

View File

@ -1,10 +1,7 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#include "finder.h"
#include <QMainWindow> #include <QMainWindow>
#include <QStandardItemModel>
#include <QStringListModel>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { namespace Ui {
@ -15,26 +12,10 @@ QT_END_NAMESPACE
class MainWindow : public QMainWindow { class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
private:
std::vector<std::string> word_list_;
QStringListModel result_model_;
QStandardItemModel search_algorithms_;
public: public:
MainWindow(QWidget *parent = nullptr); MainWindow(QWidget *parent = nullptr);
~MainWindow(); ~MainWindow();
private:
void setupAlgorithmSelector();
void generateWordList();
void search(const QString &search_term);
std::unique_ptr<Finder> createSelectedFinder() const;
void showResults(const std::vector<const std::string *> &results);
private slots:
void on_searchInput_textChanged(const QString &search_term);
void on_searchAlgorithmSelector_currentIndexChanged(int);
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
}; };

View File

@ -11,86 +11,11 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>QVectorSearch</string> <string>MainWindow</string>
</property> </property>
<property name="unifiedTitleAndToolBarOnMac"> <widget class="QWidget" name="centralwidget"/>
<bool>false</bool> <widget class="QMenuBar" name="menubar"/>
</property> <widget class="QStatusBar" name="statusbar"/>
<widget class="QWidget" name="centralwidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>1920</width>
<height>1200</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Select search algorithm</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enter a search text&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="searchAlgorithmSelector"/>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="searchInput">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListView" name="resultView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="mainStatusBar"/>
<action name="actionOption">
<property name="text">
<string>Option</string>
</property>
</action>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -1,19 +1,16 @@
#pragma once #pragma once
#include <chrono> #include <chrono>
#include <string>
class Timer { class Timer {
private: private:
std::string name_;
std::chrono::time_point<std::chrono::high_resolution_clock> start_; std::chrono::time_point<std::chrono::high_resolution_clock> start_;
std::chrono::time_point<std::chrono::high_resolution_clock> end_;
public: public:
Timer(); Timer(std::string_view name);
void start(); void start();
void stop(); void stop();
long us() const;
}; };
std::ostream &operator<<(std::ostream &os, const Timer &timer);

View File

@ -1,32 +1,17 @@
#include "timer.h" #include "timer.h"
#include <chrono> #include <chrono>
#include <iostream>
Timer::Timer() { start(); }; Timer::Timer(std::string_view name) : name_(name) { start(); };
void Timer::start() { start_ = std::chrono::high_resolution_clock::now(); } void Timer::start() { start_ = std::chrono::high_resolution_clock::now(); }
void Timer::stop() { end_ = std::chrono::high_resolution_clock::now(); } void Timer::stop() {
auto end = std::chrono::high_resolution_clock::now();
long Timer::us() const { auto duration =
return std::chrono::duration_cast<std::chrono::microseconds>(end_ - start_) std::chrono::duration_cast<std::chrono::microseconds>(end - start_);
.count();
} std::cout << name_ << " took " << duration << std::endl;
std::ostream &operator<<(std::ostream &os, const Timer &timer) {
long time = timer.us();
if (time >= 1e6) {
os << time / static_cast<long>(1e6) << " s ";
time %= static_cast<long>(1e6);
}
if (time >= 1e3) {
os << time / static_cast<long>(1e3) << " ms ";
time %= static_cast<long>(1e3);
}
os << time << " µs";
return os;
} }

View File

@ -7,7 +7,7 @@
const std::string WordListGenerator::charset_ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const std::string WordListGenerator::charset_ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::vector<std::string> WordListGenerator::generate() { std::vector<std::string> WordListGenerator::generate() {
const size_t multiplier = 1; const size_t multiplier = 10;
std::vector<std::string> result; std::vector<std::string> result;
result.reserve(multiplier * std::pow(charset_.length(), 4)); result.reserve(multiplier * std::pow(charset_.length(), 4));

View File

@ -13,11 +13,10 @@ using std::string, std::string_view, std::vector, std::thread, std::cout,
vector<string> generate_word_list() { vector<string> generate_word_list() {
cout << "\ngenerating word list" << endl; cout << "\ngenerating word list" << endl;
Timer generator_timer; Timer generator_timer("word list generator");
auto word_list = WordListGenerator().generate(); auto word_list = WordListGenerator().generate();
generator_timer.stop(); generator_timer.stop();
cout << "word list generator took " << generator_timer << endl;
cout << "word list is " << word_list.size() << " element(s) long" << endl; cout << "word list is " << word_list.size() << " element(s) long" << endl;
return word_list; return word_list;
@ -26,15 +25,14 @@ vector<string> generate_word_list() {
void test_linear_finder(const vector<string> &word_list) { void test_linear_finder(const vector<string> &word_list) {
cout << "\nrunning linear finder" << endl; cout << "\nrunning linear finder" << endl;
Timer constructor_timer; Timer constructor_timer("linear finder constructor");
LinearFinder linear_finder(word_list); LinearFinder linear_finder(word_list);
constructor_timer.stop(); constructor_timer.stop();
Timer find_timer; Timer find_timer("linear finder find");
auto result = linear_finder.find_prefix("ABCD"); auto result = linear_finder.find_prefix("ABCD");
find_timer.stop(); find_timer.stop();
cout << "linear finder took " << find_timer << endl;
cout << "result list is " << result.size() << " element(s) long" << endl; cout << "result list is " << result.size() << " element(s) long" << endl;
} }
@ -45,15 +43,14 @@ void test_parallel_finder(const vector<string> &word_list) {
cout << "using " << thread_count << " threads" << endl; cout << "using " << thread_count << " threads" << endl;
Timer constructor_timer; Timer constructor_timer("parallel finder constructor");
ParallelFinder parallel_finder(word_list, thread_count); ParallelFinder parallel_finder(word_list, thread_count);
constructor_timer.stop(); constructor_timer.stop();
Timer find_timer; Timer find_timer("parallel finder find");
auto result = parallel_finder.find_prefix("ABCD"); auto result = parallel_finder.find_prefix("ABCD");
find_timer.stop(); find_timer.stop();
cout << "parallel finder took " << find_timer << endl;
cout << "result list is " << result.size() << " element(s) long" << endl; cout << "result list is " << result.size() << " element(s) long" << endl;
} }