Added new model to store execution times

This commit is contained in:
dvanaken 2020-01-14 10:28:56 -05:00 committed by Dana Van Aken
parent 0cbc7ba334
commit 06948089d2
6 changed files with 92 additions and 10 deletions

View File

@ -13,7 +13,7 @@ profile=no
# Add files or directories to the blacklist. They should be base names, not # Add files or directories to the blacklist. They should be base names, not
# paths. # paths.
ignore=CVS,.git,manage.py,0001_initial.py,0002_enable_compression.py,0003_load_initial_data.py,0004_add_lhs.py,0005_add_workload_field.py,0006_session_hyperparameters.py,credentials.py,create_knob_settings.py ignore=CVS,.git,manage.py,0001_initial.py,0002_enable_compression.py,0003_load_initial_data.py,0004_add_lhs.py,0005_add_workload_field.py,0006_session_hyperparameters.py,0007_executiontime.py,credentials.py,create_knob_settings.py
# ignore-patterns=**/migrations/*.py # ignore-patterns=**/migrations/*.py

View File

@ -10,10 +10,10 @@ from django_db_logger.admin import StatusLogAdmin
from django_db_logger.models import StatusLog from django_db_logger.models import StatusLog
from djcelery import models as djcelery_models from djcelery import models as djcelery_models
from .models import (BackupData, DBMSCatalog, KnobCatalog, from .models import (BackupData, DBMSCatalog, ExecutionTime,
KnobData, MetricCatalog, MetricData, KnobCatalog, KnobData, MetricCatalog,
PipelineData, PipelineRun, Project, MetricData, PipelineData, PipelineRun,
Result, Session, Workload, Hardware, Project, Result, Session, Workload, Hardware,
SessionKnob) SessionKnob)
from .types import VarType from .types import VarType
@ -175,6 +175,14 @@ class CustomStatusLogAdmin(StatusLogAdmin):
list_filter = ('logger_name', 'level') list_filter = ('logger_name', 'level')
class ExecutionTimeAdmin(admin.ModelAdmin):
list_display = ('event', 'result', 'exec_time')
def exec_time(self, instance): # pylint: disable=no-self-use
return '{:.0f} sec'.format(instance.execution_time)
exec_time.short_description = 'Execution Time'
# Admin classes for website models # Admin classes for website models
admin.site.register(DBMSCatalog, DBMSCatalogAdmin) admin.site.register(DBMSCatalog, DBMSCatalogAdmin)
admin.site.register(KnobCatalog, KnobCatalogAdmin) admin.site.register(KnobCatalog, KnobCatalogAdmin)
@ -190,6 +198,7 @@ admin.site.register(PipelineRun, PipelineRunAdmin)
admin.site.register(Workload, WorkloadAdmin) admin.site.register(Workload, WorkloadAdmin)
admin.site.register(SessionKnob, SessionKnobAdmin) admin.site.register(SessionKnob, SessionKnobAdmin)
admin.site.register(Hardware, HardwareAdmin) admin.site.register(Hardware, HardwareAdmin)
admin.site.register(ExecutionTime, ExecutionTimeAdmin)
# Admin classes for 3rd party models # Admin classes for 3rd party models
admin.site.unregister(StatusLog) admin.site.unregister(StatusLog)

View File

@ -17,6 +17,7 @@ class NewResultForm(forms.Form):
metrics_after = forms.FileField() metrics_after = forms.FileField()
knobs = forms.FileField() knobs = forms.FileField()
summary = forms.FileField() summary = forms.FileField()
execution_times = forms.CharField(required=False, strip=True)
class ProjectForm(forms.ModelForm): class ProjectForm(forms.ModelForm):

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.27 on 2020-01-24 00:15
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('website', '0006_session_hyperparameters'),
]
operations = [
migrations.CreateModel(
name='ExecutionTime',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('module', models.CharField(max_length=32)),
('function', models.CharField(max_length=32)),
('tag', models.CharField(blank=True, default='', max_length=64)),
('start_time', models.DateTimeField()),
('execution_time', models.FloatField()),
('result', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='website.Result')),
],
),
]

View File

@ -4,12 +4,15 @@
# Copyright (c) 2017-18, Carnegie Mellon University Database Group # Copyright (c) 2017-18, Carnegie Mellon University Database Group
# #
from collections import OrderedDict from collections import OrderedDict
from pytz import timezone
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db import models, DEFAULT_DB_ALIAS from django.db import models, DEFAULT_DB_ALIAS
from django.utils.datetime_safe import datetime
from django.utils.timezone import now from django.utils.timezone import now
from .db import target_objectives from .db import target_objectives
from .settings import TIME_ZONE
from .types import (DBMSType, LabelStyleType, MetricType, KnobUnitType, from .types import (DBMSType, LabelStyleType, MetricType, KnobUnitType,
PipelineTaskType, VarType, KnobResourceType, PipelineTaskType, VarType, KnobResourceType,
WorkloadStatusType, AlgorithmType, StorageType) WorkloadStatusType, AlgorithmType, StorageType)
@ -498,3 +501,22 @@ class BackupData(BaseModel):
raw_summary = models.TextField() raw_summary = models.TextField()
knob_log = models.TextField() knob_log = models.TextField()
metric_log = models.TextField() metric_log = models.TextField()
class ExecutionTime(models.Model):
module = models.CharField(max_length=32)
function = models.CharField(max_length=32)
tag = models.CharField(max_length=64, blank=True, default='')
start_time = models.DateTimeField()
execution_time = models.FloatField() # in seconds
result = models.ForeignKey(Result, null=True, blank=True, default=None)
@property
def event(self):
return '.'.join((e for e in (self.module, self.function, self.tag) if e))
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
if isinstance(self.start_time, (int, float)):
self.start_time = datetime.fromtimestamp(int(self.start_time), timezone(TIME_ZONE))
super().save(force_insert=force_insert, force_update=force_update, using=using,
update_fields=update_fields)

View File

@ -4,12 +4,13 @@
# Copyright (c) 2017-18, Carnegie Mellon University Database Group # Copyright (c) 2017-18, Carnegie Mellon University Database Group
# #
# pylint: disable=too-many-lines # pylint: disable=too-many-lines
import csv
import logging import logging
import datetime
import os import os
import re import re
import shutil import shutil
from collections import OrderedDict from collections import OrderedDict
from io import StringIO
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
@ -34,8 +35,9 @@ from pytz import timezone
from . import utils from . import utils
from .db import parser, target_objectives from .db import parser, target_objectives
from .forms import NewResultForm, ProjectForm, SessionForm, SessionKnobForm from .forms import NewResultForm, ProjectForm, SessionForm, SessionKnobForm
from .models import (BackupData, DBMSCatalog, KnobCatalog, KnobData, MetricCatalog, User, Hardware, from .models import (BackupData, DBMSCatalog, ExecutionTime, Hardware, KnobCatalog, KnobData,
MetricData, Project, Result, Session, Workload, SessionKnob, PipelineRun) MetricCatalog, MetricData, PipelineRun, Project, Result, Session,
SessionKnob, User, Workload)
from .tasks import (aggregate_target_results, map_workload, train_ddpg, from .tasks import (aggregate_target_results, map_workload, train_ddpg,
configuration_recommendation, configuration_recommendation_ddpg) configuration_recommendation, configuration_recommendation_ddpg)
from .types import (DBMSType, KnobUnitType, MetricType, from .types import (DBMSType, KnobUnitType, MetricType,
@ -457,12 +459,13 @@ def new_result(request):
LOG.warning("Invalid upload code: %s", upload_code) LOG.warning("Invalid upload code: %s", upload_code)
return HttpResponse("Invalid upload code: " + upload_code, status=400) return HttpResponse("Invalid upload code: " + upload_code, status=400)
return handle_result_files(session, request.FILES) execution_times = form.cleaned_data['execution_times']
return handle_result_files(session, request.FILES, execution_times)
LOG.warning("Request type was not POST") LOG.warning("Request type was not POST")
return HttpResponse("Request type was not POST", status=400) return HttpResponse("Request type was not POST", status=400)
def handle_result_files(session, files): def handle_result_files(session, files, execution_times=None):
from celery import chain from celery import chain
# Combine into contiguous files # Combine into contiguous files
files = {k: b''.join(v.chunks()).decode() for k, v in list(files.items())} files = {k: b''.join(v.chunks()).decode() for k, v in list(files.items())}
@ -653,6 +656,25 @@ def handle_result_files(session, files):
result.task_ids = ','.join(taskmeta_ids) result.task_ids = ','.join(taskmeta_ids)
result.save() result.save()
if execution_times:
try:
batch = []
f = StringIO(execution_times)
reader = csv.reader(f, delimiter=',')
for module, fn, tag, start_ts, end_ts in reader:
start_ts = float(start_ts)
end_ts = float(end_ts)
exec_time = end_ts - start_ts
start_time = datetime.fromtimestamp(int(start_ts), timezone(TIME_ZONE))
batch.append(
ExecutionTime(module=module, function=fn, tag=tag, start_time=start_time,
execution_time=exec_time, result=result))
ExecutionTime.objects.bulk_create(batch)
except Exception: # pylint: disable=broad-except
LOG.warning("Error parsing execution times:\n%s", execution_times, exc_info=True)
return HttpResponse("Result stored successfully! Running tuner...(status={}) Result ID:{} " return HttpResponse("Result stored successfully! Running tuner...(status={}) Result ID:{} "
.format(response.status, result_id)) .format(response.status, result_id))