1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08: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 {DirectoryDTO} from '../src/common/entities/DirectoryDTO';
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);
@ -30,7 +33,7 @@ export class BMIndexingManager extends IndexingManager {
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('./'));
}
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 }[]> {
await this.setupDB();
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));
}
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>,
beforeEach: () => Promise<any> = null,
@ -122,9 +149,8 @@ export class Benchmarks {
private resetDB = async () => {
await SQLConnection.close();
await rimrafPR(this.dbFolder);
await rimrafPR(ProjectPath.DBFolder);
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.dbFolder = this.dbFolder;
await ObjectManagers.InitSQLManagers();
};

View File

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

View File

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

View File

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

View File

@ -97,6 +97,6 @@ export class PersonMWs {
}
export interface PersonWithPhoto extends PersonDTO {
export interface PersonWithPhoto extends PersonDTO {
samplePhoto: PhotoDTO;
}

View File

@ -14,7 +14,7 @@ export class UserManager implements IUserManager {
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)) {
this.loadDB();
}

View File

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

View File

@ -17,7 +17,7 @@ export class JobProgressManager {
private timer: NodeJS.Timeout = null;
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);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -13,6 +13,7 @@ import {SuperAgentStatic} from 'superagent';
import {RouteTestingHelper} from './RouteTestingHelper';
import {ErrorCodes} from '../../../../src/common/entities/Error';
import {ServerConfig} from '../../../../src/common/config/private/PrivateConfig';
import {ProjectPath} from '../../../../src/backend/ProjectPath';
process.env.NODE_ENV = 'test';
@ -39,6 +40,7 @@ describe('UserRouter', () => {
Config.Server.Threading.enabled = false;
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.dbFolder = tempDir;
ProjectPath.reset();
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 {Server} from '../../../../../src/backend/server';
import {ServerConfig} from '../../../../../src/common/config/private/PrivateConfig';
import {ProjectPath} from '../../../../../src/backend/ProjectPath';
process.env.NODE_ENV = 'test';
const chai: any = require('chai');
@ -21,6 +22,7 @@ describe('SettingsRouter', () => {
Config.Server.Threading.enabled = false;
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.dbFolder = tempDir;
ProjectPath.reset();
});