1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-11-25 22:32:52 +02:00

improving benchmark

This commit is contained in:
Patrik J. Braun
2020-12-28 22:08:57 +01:00
parent d2cdc32c68
commit 03789ecaf8
15 changed files with 103 additions and 13 deletions

39
benchmark/BMConfig.ts Normal file
View File

@@ -0,0 +1,39 @@
/* tslint:disable:no-inferrable-types */
import * as path from 'path';
import {ConfigClass, ConfigClassBuilder} from 'typeconfig/node';
import {ConfigProperty} from 'typeconfig/common';
@ConfigClass({
configPath: path.join(__dirname, './../bm_config.json'),
saveIfNotExist: true,
attachDescription: true,
enumsAsString: true,
softReadonly: true,
cli: {
enable: {
configPath: true,
attachState: true,
attachDescription: true,
rewriteCLIConfig: true,
rewriteENVConfig: true,
enumsAsString: true,
saveIfNotExist: true,
exitOnConfig: true
},
defaults: {
enabled: true
}
}
})
export class PrivateConfigClass {
@ConfigProperty({description: 'Images are loaded from this folder (read permission required)'})
path: string = 'demo/images';
@ConfigProperty({description: 'Describe your system setup'})
system: string = '';
}
export const BMConfig = ConfigClassBuilder.attachInterface(new PrivateConfigClass());
BMConfig.loadSync();

View File

@@ -11,6 +11,9 @@ import {Utils} from '../src/common/Utils';
import {GalleryManager} from '../src/backend/model/database/sql/GalleryManager'; import {GalleryManager} from '../src/backend/model/database/sql/GalleryManager';
import {DirectoryDTO} from '../src/common/entities/DirectoryDTO'; import {DirectoryDTO} from '../src/common/entities/DirectoryDTO';
import {ServerConfig} from '../src/common/config/private/PrivateConfig'; import {ServerConfig} from '../src/common/config/private/PrivateConfig';
import {ProjectPath} from '../src/backend/ProjectPath';
import {PersonMWs} from '../src/backend/middlewares/PersonMWs';
import {ThumbnailGeneratorMWs} from '../src/backend/middlewares/thumbnail/ThumbnailGeneratorMWs';
const rimrafPR = util.promisify(rimraf); const rimrafPR = util.promisify(rimraf);
@@ -30,7 +33,7 @@ export class BMIndexingManager extends IndexingManager {
export class Benchmarks { export class Benchmarks {
constructor(public RUNS: number, public dbFolder: string) { constructor(public RUNS: number) {
} }
@@ -52,6 +55,20 @@ export class Benchmarks {
return await this.benchmark(() => gm.listDirectory('./')); return await this.benchmark(() => gm.listDirectory('./'));
} }
async bmListPersons(): Promise<BenchmarkResult> {
await this.setupDB();
Config.Server.Indexing.reIndexingSensitivity = ServerConfig.ReIndexingSensitivity.low;
return await this.benchmark(async () => {
await ObjectManagers.reset();
const req = {resultPipe: <any>null};
await this.nextToPromise(PersonMWs.listPersons, req, null);
await this.nextToPromise(PersonMWs.addSamplePhotoForAll, req, null);
await this.nextToPromise(ThumbnailGeneratorMWs.addThumbnailInfoForPersons, req, null);
await this.nextToPromise(PersonMWs.removeSamplePhotoForAll, req, null);
return req.resultPipe;
});
}
async bmAllSearch(text: string): Promise<{ result: BenchmarkResult, searchType: SearchTypes }[]> { async bmAllSearch(text: string): Promise<{ result: BenchmarkResult, searchType: SearchTypes }[]> {
await this.setupDB(); await this.setupDB();
const types = Utils.enumToArray(SearchTypes).map(a => a.key).concat([null]); const types = Utils.enumToArray(SearchTypes).map(a => a.key).concat([null]);
@@ -75,6 +92,16 @@ export class Benchmarks {
return await this.benchmark(() => sm.autocomplete(text)); return await this.benchmark(() => sm.autocomplete(text));
} }
private nextToPromise(fn: (req: any, res: any, next: Function) => void, request: any, response: any) {
return new Promise<void>((resolve, reject) => {
fn(request, resolve, (err?: any) => {
if (err) {
return reject(err);
}
resolve();
});
});
}
private async benchmark(fn: () => Promise<{ media: any[], directories: any[] } | any[] | void>, private async benchmark(fn: () => Promise<{ media: any[], directories: any[] } | any[] | void>,
beforeEach: () => Promise<any> = null, beforeEach: () => Promise<any> = null,
@@ -122,9 +149,8 @@ export class Benchmarks {
private resetDB = async () => { private resetDB = async () => {
await SQLConnection.close(); await SQLConnection.close();
await rimrafPR(this.dbFolder); await rimrafPR(ProjectPath.DBFolder);
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite; Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.dbFolder = this.dbFolder;
await ObjectManagers.InitSQLManagers(); await ObjectManagers.InitSQLManagers();
}; };

View File

@@ -5,10 +5,12 @@ import {BenchmarkResult, Benchmarks} from './Benchmarks';
import {SearchTypes} from '../src/common/entities/AutoCompleteItem'; import {SearchTypes} from '../src/common/entities/AutoCompleteItem';
import {Utils} from '../src/common/Utils'; import {Utils} from '../src/common/Utils';
import {DiskMangerWorker} from '../src/backend/model/threading/DiskMangerWorker'; import {DiskMangerWorker} from '../src/backend/model/threading/DiskMangerWorker';
import {BMConfig} from './BMConfig';
import {GalleryManager} from '../src/backend/model/database/sql/GalleryManager';
const config: { path: string, system: string } = require(path.join(__dirname, 'config.json'));
Config.Server.Media.folder = config.path; Config.Server.Media.folder = BMConfig.path;
const dbFolder = __dirname; const dbFolder = path.join(__dirname, './../');
ProjectPath.reset(); ProjectPath.reset();
const RUNS = 50; const RUNS = 50;
@@ -23,8 +25,9 @@ const printHeader = async () => {
', ' + Utils.zeroPrefix(dt.getDate(), 2) + ', ' + Utils.zeroPrefix(dt.getDate(), 2) +
'.' + Utils.zeroPrefix(dt.getMonth() + 1, 2) + '.' + Utils.zeroPrefix(dt.getMonth() + 1, 2) +
'.' + dt.getFullYear()); '.' + dt.getFullYear());
printLine('**System**: ' + config.system); printLine('**System**: ' + BMConfig.system);
const dir = await DiskMangerWorker.scanDirectory('./'); const dir = await DiskMangerWorker.scanDirectory('./');
const gm = new GalleryManager();
printLine('**Gallery**: directories: ' + printLine('**Gallery**: directories: ' +
dir.directories.length + dir.directories.length +
' media: ' + dir.media.length + ' media: ' + dir.media.length +
@@ -52,7 +55,7 @@ const printResult = (result: BenchmarkResult, action: string, actionDetails: str
const run = async () => { const run = async () => {
const start = Date.now(); const start = Date.now();
const bm = new Benchmarks(RUNS, dbFolder); const bm = new Benchmarks(RUNS);
// header // header
await printHeader(); await printHeader();
@@ -60,6 +63,7 @@ const run = async () => {
printResult(await bm.bmScanDirectory(), 'Scanning directory'); printResult(await bm.bmScanDirectory(), 'Scanning directory');
printResult(await bm.bmSaveDirectory(), 'Saving directory'); printResult(await bm.bmSaveDirectory(), 'Saving directory');
printResult(await bm.bmListDirectory(), 'Listing Directory'); printResult(await bm.bmListDirectory(), 'Listing Directory');
printResult(await bm.bmListPersons(), 'Listing Faces');
(await bm.bmAllSearch('a')).forEach(res => { (await bm.bmAllSearch('a')).forEach(res => {
if (res.searchType !== null) { if (res.searchType !== null) {
printResult(res.result, 'searching', '`a` as `' + SearchTypes[res.searchType] + '`'); printResult(res.result, 'searching', '`a` as `' + SearchTypes[res.searchType] + '`');

View File

@@ -146,7 +146,7 @@
"@ffprobe-installer/ffprobe": "1.1.0", "@ffprobe-installer/ffprobe": "1.1.0",
"bcrypt": "5.0.0", "bcrypt": "5.0.0",
"mysql": "2.18.1", "mysql": "2.18.1",
"sharp": "0.27.0" "sharp": "0.23.4"
}, },
"engines": { "engines": {
"node": ">=10.17 <15.0" "node": ">=10.17 <15.0"

View File

@@ -9,6 +9,7 @@ class ProjectPathClass {
public TranscodedFolder: string; public TranscodedFolder: string;
public FacesFolder: string; public FacesFolder: string;
public FrontendFolder: string; public FrontendFolder: string;
public DBFolder: string;
constructor() { constructor() {
this.reset(); this.reset();
@@ -33,6 +34,7 @@ class ProjectPathClass {
this.TempFolder = this.getAbsolutePath(Config.Server.Media.tempFolder); this.TempFolder = this.getAbsolutePath(Config.Server.Media.tempFolder);
this.TranscodedFolder = path.join(this.TempFolder, 'tc'); this.TranscodedFolder = path.join(this.TempFolder, 'tc');
this.FacesFolder = path.join(this.TempFolder, 'f'); this.FacesFolder = path.join(this.TempFolder, 'f');
this.DBFolder = this.getAbsolutePath(Config.Server.Database.dbFolder);
// create thumbnail folder if not exist // create thumbnail folder if not exist
if (!fs.existsSync(this.TempFolder)) { if (!fs.existsSync(this.TempFolder)) {

View File

@@ -14,7 +14,7 @@ export class UserManager implements IUserManager {
constructor() { constructor() {
this.dbPath = path.join(ProjectPath.getAbsolutePath(Config.Server.Database.dbFolder), 'users.db'); this.dbPath = path.join(ProjectPath.DBFolder, 'users.db');
if (fs.existsSync(this.dbPath)) { if (fs.existsSync(this.dbPath)) {
this.loadDB(); this.loadDB();
} }

View File

@@ -183,7 +183,7 @@ export class SQLConnection {
} else if (config.type === ServerConfig.DatabaseType.sqlite) { } else if (config.type === ServerConfig.DatabaseType.sqlite) {
driver = { driver = {
type: 'sqlite', type: 'sqlite',
database: path.join(ProjectPath.getAbsolutePath(config.dbFolder), 'sqlite.db') database: path.join(ProjectPath.getAbsolutePath(config.dbFolder), config.sqlite.DBFileName)
}; };
} }
return driver; return driver;

View File

@@ -17,7 +17,7 @@ export class JobProgressManager {
private timer: NodeJS.Timeout = null; private timer: NodeJS.Timeout = null;
constructor() { constructor() {
this.dbPath = path.join(ProjectPath.getAbsolutePath(Config.Server.Database.dbFolder), 'jobs.db'); this.dbPath = path.join(ProjectPath.DBFolder, 'jobs.db');
this.loadDB().catch(console.error); this.loadDB().catch(console.error);
} }

View File

@@ -53,6 +53,13 @@ export module ServerConfig {
} }
@SubConfigClass()
export class SQLiteConfig {
@ConfigProperty()
DBFileName: string = 'sqlite.db';
}
@SubConfigClass() @SubConfigClass()
export class DataBaseConfig { export class DataBaseConfig {
@ConfigProperty<DatabaseType, IPrivateConfig>({ @ConfigProperty<DatabaseType, IPrivateConfig>({
@@ -69,6 +76,9 @@ export module ServerConfig {
@ConfigProperty() @ConfigProperty()
dbFolder: string = 'db'; dbFolder: string = 'db';
@ConfigProperty()
sqlite?: SQLiteConfig = new SQLiteConfig();
@ConfigProperty() @ConfigProperty()
mysql?: MySQLConfig = new MySQLConfig(); mysql?: MySQLConfig = new MySQLConfig();
} }

View File

@@ -4,6 +4,7 @@ import * as util from 'util';
import * as rimraf from 'rimraf'; import * as rimraf from 'rimraf';
import {SQLConnection} from '../../src/backend/model/database/sql/SQLConnection'; import {SQLConnection} from '../../src/backend/model/database/sql/SQLConnection';
import {ServerConfig} from '../../src/common/config/private/PrivateConfig'; import {ServerConfig} from '../../src/common/config/private/PrivateConfig';
import {ProjectPath} from '../../src/backend/ProjectPath';
declare let describe: any; declare let describe: any;
const savedDescribe = describe; const savedDescribe = describe;
@@ -63,6 +64,7 @@ export class SQLTestHelper {
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite; Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.dbFolder = this.tempDir; Config.Server.Database.dbFolder = this.tempDir;
ProjectPath.reset();
} }
private async initMySQL() { private async initMySQL() {

View File

@@ -18,6 +18,7 @@ import {
import {MediaDimensionEntity} from '../../../../../src/backend/model/database/sql/enitites/MediaEntity'; import {MediaDimensionEntity} from '../../../../../src/backend/model/database/sql/enitites/MediaEntity';
import {VersionEntity} from '../../../../../src/backend/model/database/sql/enitites/VersionEntity'; import {VersionEntity} from '../../../../../src/backend/model/database/sql/enitites/VersionEntity';
import {ServerConfig} from '../../../../../src/common/config/private/PrivateConfig'; import {ServerConfig} from '../../../../../src/common/config/private/PrivateConfig';
import {ProjectPath} from '../../../../../src/backend/ProjectPath';
const rimrafPR = util.promisify(rimraf); const rimrafPR = util.promisify(rimraf);
@@ -31,6 +32,7 @@ describe('Typeorm integration', () => {
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite; Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.dbFolder = tempDir; Config.Server.Database.dbFolder = tempDir;
ProjectPath.reset();
}; };

View File

@@ -30,6 +30,7 @@ describe('GalleryRouter', () => {
Config.Server.Database.dbFolder = tempDir; Config.Server.Database.dbFolder = tempDir;
ProjectPath.ImageFolder = path.join(__dirname, '../../assets'); ProjectPath.ImageFolder = path.join(__dirname, '../../assets');
ProjectPath.TempFolder = tempDir; ProjectPath.TempFolder = tempDir;
ProjectPath.reset();
server = new Server(); server = new Server();
await server.onStarted.wait(); await server.onStarted.wait();

View File

@@ -13,6 +13,7 @@ import {SuperAgentStatic} from 'superagent';
import {RouteTestingHelper} from './RouteTestingHelper'; import {RouteTestingHelper} from './RouteTestingHelper';
import {ErrorCodes} from '../../../../src/common/entities/Error'; import {ErrorCodes} from '../../../../src/common/entities/Error';
import {ServerConfig} from '../../../../src/common/config/private/PrivateConfig'; import {ServerConfig} from '../../../../src/common/config/private/PrivateConfig';
import {ProjectPath} from '../../../../src/backend/ProjectPath';
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
@@ -39,6 +40,7 @@ describe('UserRouter', () => {
Config.Server.Threading.enabled = false; Config.Server.Threading.enabled = false;
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite; Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.dbFolder = tempDir; Config.Server.Database.dbFolder = tempDir;
ProjectPath.reset();
server = new Server(); server = new Server();

View File

@@ -5,6 +5,7 @@ import {Config} from '../../../../../src/common/config/private/Config';
import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection'; import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection';
import {Server} from '../../../../../src/backend/server'; import {Server} from '../../../../../src/backend/server';
import {ServerConfig} from '../../../../../src/common/config/private/PrivateConfig'; import {ServerConfig} from '../../../../../src/common/config/private/PrivateConfig';
import {ProjectPath} from '../../../../../src/backend/ProjectPath';
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
const chai: any = require('chai'); const chai: any = require('chai');
@@ -21,6 +22,7 @@ describe('SettingsRouter', () => {
Config.Server.Threading.enabled = false; Config.Server.Threading.enabled = false;
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite; Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.dbFolder = tempDir; Config.Server.Database.dbFolder = tempDir;
ProjectPath.reset();
}); });