Compare commits
6 Commits
c307783ef2
...
9a855daabf
Author | SHA1 | Date |
---|---|---|
mandlm | 9a855daabf | |
mandlm | 2a8b342b91 | |
mandlm | e2f9b630c5 | |
mandlm | 42b8c8d7e7 | |
mandlm | 64ae4c62a9 | |
mandlm | f7634bdd95 |
|
@ -33,7 +33,8 @@ 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,
|
||||||
|
|
|
@ -1,9 +1,95 @@
|
||||||
#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());
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#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 {
|
||||||
|
@ -12,10 +15,26 @@ 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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,11 +11,86 @@
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>MainWindow</string>
|
<string>QVectorSearch</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget"/>
|
<property name="unifiedTitleAndToolBarOnMac">
|
||||||
<widget class="QMenuBar" name="menubar"/>
|
<bool>false</bool>
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
</property>
|
||||||
|
<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><html><head/><body><p>Enter a search text</p></body></html></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/>
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
#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(std::string_view name);
|
Timer();
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
long us() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, const Timer &timer);
|
||||||
|
|
|
@ -1,17 +1,32 @@
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
Timer::Timer(std::string_view name) : name_(name) { start(); };
|
Timer::Timer() { start(); };
|
||||||
|
|
||||||
void Timer::start() { start_ = std::chrono::high_resolution_clock::now(); }
|
void Timer::start() { start_ = std::chrono::high_resolution_clock::now(); }
|
||||||
|
|
||||||
void Timer::stop() {
|
void Timer::stop() { end_ = std::chrono::high_resolution_clock::now(); }
|
||||||
auto end = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
auto duration =
|
long Timer::us() const {
|
||||||
std::chrono::duration_cast<std::chrono::microseconds>(end - start_);
|
return 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = 10;
|
const size_t multiplier = 1;
|
||||||
|
|
||||||
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));
|
||||||
|
|
|
@ -13,10 +13,11 @@ 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("word list generator");
|
Timer generator_timer;
|
||||||
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;
|
||||||
|
@ -25,14 +26,15 @@ 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("linear finder constructor");
|
Timer constructor_timer;
|
||||||
LinearFinder linear_finder(word_list);
|
LinearFinder linear_finder(word_list);
|
||||||
constructor_timer.stop();
|
constructor_timer.stop();
|
||||||
|
|
||||||
Timer find_timer("linear finder find");
|
Timer find_timer;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,14 +45,15 @@ void test_parallel_finder(const vector<string> &word_list) {
|
||||||
|
|
||||||
cout << "using " << thread_count << " threads" << endl;
|
cout << "using " << thread_count << " threads" << endl;
|
||||||
|
|
||||||
Timer constructor_timer("parallel finder constructor");
|
Timer constructor_timer;
|
||||||
ParallelFinder parallel_finder(word_list, thread_count);
|
ParallelFinder parallel_finder(word_list, thread_count);
|
||||||
constructor_timer.stop();
|
constructor_timer.stop();
|
||||||
|
|
||||||
Timer find_timer("parallel finder find");
|
Timer find_timer;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue