8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-27 20:03:03 +01:00
firebird-mirror/src/jrd/perf.cpp

408 lines
8.9 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Access Method
* MODULE: perf.cpp
2001-05-23 15:26:42 +02:00
* DESCRIPTION: Performance monitoring routines
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
2002-02-16 04:05:21 +01:00
*
* 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "DELTA" port
2002-02-16 04:27:33 +01:00
* 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "IMP" port
2002-02-16 04:05:21 +01:00
*
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
*
2001-05-23 15:26:42 +02:00
*/
#include "firebird.h"
2004-04-29 00:43:34 +02:00
#include <stdio.h>
2001-05-23 15:26:42 +02:00
#include <limits.h>
#include "../jrd/common.h"
2003-11-08 17:40:17 +01:00
#include "../jrd/ibase.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/perf.h"
#include "../jrd/gds_proto.h"
#include "../jrd/perf_proto.h"
#include "../jrd/gdsassert.h"
#if defined(TIME_WITH_SYS_TIME)
#include <sys/time.h>
#include <time.h>
2008-03-28 14:33:39 +01:00
#elif defined(HAVE_SYS_TIME_H)
#include <sys/time.h>
#else
2008-03-26 11:03:48 +01:00
#include <time.h>
#endif
#ifdef HAVE_SYS_TIMEB_H
2008-03-26 11:03:48 +01:00
#include <sys/timeb.h>
#endif
2001-05-23 15:26:42 +02:00
static SINT64 get_parameter(const SCHAR**);
#ifndef HAVE_TIMES
static void times(struct tms*);
2001-05-23 15:26:42 +02:00
#endif
2009-01-20 09:33:59 +01:00
static const SCHAR items[] =
2008-12-22 10:00:05 +01:00
{
isc_info_reads,
isc_info_writes,
isc_info_fetches,
2001-05-23 15:26:42 +02:00
isc_info_marks,
isc_info_page_size, isc_info_num_buffers,
isc_info_current_memory, isc_info_max_memory
};
2008-12-22 10:00:05 +01:00
static const SCHAR* report = "elapsed = !e cpu = !u reads = !r writes = !w fetches = !f marks = !m$";
2001-05-23 15:26:42 +02:00
2002-06-12 09:07:32 +02:00
#if defined(WIN_NT) && !defined(CLOCKS_PER_SEC)
2001-05-23 15:26:42 +02:00
#define TICK 100
#endif
/* EKU: TICK (sys/param.h) and CLOCKS_PER_SEC (time.h) may both be defined */
#if !defined(TICK) && defined(CLOCKS_PER_SEC)
2006-01-18 11:43:13 +01:00
#define TICK ((SLONG)CLOCKS_PER_SEC)
#endif
2001-05-23 15:26:42 +02:00
#ifndef TICK
2006-01-18 11:43:13 +01:00
#define TICK ((SLONG)CLK_TCK)
2001-05-23 15:26:42 +02:00
#endif
template<typename P>
static int perf_format(const P* before, const P* after,
const SCHAR* string, SCHAR* buffer, SSHORT* buf_len)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* P E R F _ f o r m a t
*
**************************************
*
* Functional description
* Format a buffer with statistical stuff under control of formatting
* string. Substitute in appropriate stuff. Return the length of the
* formatting output.
*
**************************************/
SCHAR c;
2001-05-23 15:26:42 +02:00
2009-02-28 12:57:40 +01:00
SLONG buffer_length = buf_len ? *buf_len : 0;
SCHAR* p = buffer;
2001-05-23 15:26:42 +02:00
2009-01-20 09:33:59 +01:00
while ((c = *string++) && c != '$')
{
2001-05-23 15:26:42 +02:00
if (c != '!')
*p++ = c;
2009-02-28 12:57:40 +01:00
else
{
SINT64 delta;
2009-01-20 09:33:59 +01:00
switch (c = *string++)
{
2001-05-23 15:26:42 +02:00
case 'r':
delta = after->perf_reads - before->perf_reads;
break;
case 'w':
delta = after->perf_writes - before->perf_writes;
break;
case 'f':
delta = after->perf_fetches - before->perf_fetches;
break;
case 'm':
delta = after->perf_marks - before->perf_marks;
break;
case 'd':
2008-12-22 10:00:05 +01:00
delta = after->perf_current_memory - before->perf_current_memory;
2001-05-23 15:26:42 +02:00
break;
case 'p':
delta = after->perf_page_size;
break;
case 'b':
delta = after->perf_buffers;
break;
case 'c':
delta = after->perf_current_memory;
break;
case 'x':
delta = after->perf_max_memory;
break;
case 'e':
delta = after->perf_elapsed - before->perf_elapsed;
break;
case 'u':
2008-12-22 10:00:05 +01:00
delta = after->perf_times.tms_utime - before->perf_times.tms_utime;
2001-05-23 15:26:42 +02:00
break;
case 's':
2008-12-22 10:00:05 +01:00
delta = after->perf_times.tms_stime - before->perf_times.tms_stime;
2001-05-23 15:26:42 +02:00
break;
default:
sprintf(p, "?%c?", c);
while (*p)
p++;
}
2009-01-20 09:33:59 +01:00
switch (c)
{
2001-05-23 15:26:42 +02:00
case 'r':
case 'w':
case 'f':
case 'm':
case 'd':
case 'p':
case 'b':
case 'c':
case 'x':
sprintf(p, "%"SQUADFORMAT, delta);
2001-05-23 15:26:42 +02:00
while (*p)
p++;
break;
case 'u':
case 's':
2009-09-23 17:43:33 +02:00
sprintf(p, "%"SQUADFORMAT".%.2"SQUADFORMAT, delta / TICK, (delta % TICK) * 100 / TICK);
2001-05-23 15:26:42 +02:00
while (*p)
p++;
break;
case 'e':
2009-09-23 17:43:33 +02:00
sprintf(p, "%"SQUADFORMAT".%.2"SQUADFORMAT, delta / 100, delta % 100);
2001-05-23 15:26:42 +02:00
while (*p)
p++;
break;
}
}
}
2001-05-23 15:26:42 +02:00
*p = 0;
const int length = p - buffer;
if (buffer_length && (buffer_length -= length) >= 0) {
memset(p, ' ', buffer_length);
}
2001-05-23 15:26:42 +02:00
return length;
}
template<typename P>
static void perf_get_info(FB_API_HANDLE* handle, P* perf)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* P E R F _ g e t _ i n f o
*
**************************************
*
* Functional description
* Acquire timing and performance information. Some info comes
* from the system and some from the database.
*
**************************************/
SSHORT buffer_length, item_length;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY jrd_status;
#ifdef HAVE_GETTIMEOFDAY
struct timeval tp;
#else
2001-05-23 15:26:42 +02:00
struct timeb time_buffer;
#define LARGE_NUMBER 696600000 /* to avoid overflow, get rid of decades) */
#endif
/* If there isn't a database, zero everything out */
if (!*handle) {
memset(perf, 0, sizeof(PERF));
2001-05-23 15:26:42 +02:00
}
/* Get system times */
times(&perf->perf_times);
#ifdef HAVE_GETTIMEOFDAY
2003-10-31 12:33:45 +01:00
GETTIMEOFDAY(&tp);
perf->perf_elapsed = tp.tv_sec * 100 + tp.tv_usec / 10000;
#else
2001-05-23 15:26:42 +02:00
ftime(&time_buffer);
2008-12-22 10:00:05 +01:00
perf->perf_elapsed = (time_buffer.time - LARGE_NUMBER) * 100 + (time_buffer.millitm / 10);
#endif
2001-05-23 15:26:42 +02:00
if (!*handle)
return;
SCHAR buffer[256];
2001-05-23 15:26:42 +02:00
buffer_length = sizeof(buffer);
item_length = sizeof(items);
2008-12-22 10:00:05 +01:00
isc_database_info(jrd_status, handle, item_length, items, buffer_length, buffer);
2001-05-23 15:26:42 +02:00
const char* p = buffer;
2001-05-23 15:26:42 +02:00
while (true)
2008-02-24 04:23:40 +01:00
switch (*p++)
{
2001-05-23 15:26:42 +02:00
case isc_info_reads:
perf->perf_reads = get_parameter(&p);
break;
case isc_info_writes:
perf->perf_writes = get_parameter(&p);
break;
case isc_info_marks:
perf->perf_marks = get_parameter(&p);
break;
case isc_info_fetches:
perf->perf_fetches = get_parameter(&p);
break;
case isc_info_num_buffers:
perf->perf_buffers = get_parameter(&p);
break;
case isc_info_page_size:
perf->perf_page_size = get_parameter(&p);
break;
case isc_info_current_memory:
perf->perf_current_memory = get_parameter(&p);
break;
case isc_info_max_memory:
perf->perf_max_memory = get_parameter(&p);
break;
case isc_info_end:
return;
case isc_info_error:
2008-02-24 04:23:40 +01:00
switch (p[2])
{
case isc_info_marks:
2001-05-23 15:26:42 +02:00
perf->perf_marks = 0;
2008-02-24 04:23:40 +01:00
break;
case isc_info_current_memory:
2001-05-23 15:26:42 +02:00
perf->perf_current_memory = 0;
2008-02-24 04:23:40 +01:00
break;
case isc_info_max_memory:
2001-05-23 15:26:42 +02:00
perf->perf_max_memory = 0;
2008-02-24 04:23:40 +01:00
break;
}
2008-02-26 03:23:28 +01:00
2001-05-23 15:26:42 +02:00
{
const SLONG temp = isc_vax_integer(p, 2);
2003-11-04 00:59:24 +01:00
fb_assert(temp <= MAX_SSHORT);
p += temp + 2;
2001-05-23 15:26:42 +02:00
}
2008-02-26 03:23:28 +01:00
2001-05-23 15:26:42 +02:00
perf->perf_marks = 0;
break;
default:
return;
}
}
template<typename P>
static void perf_report(const P* before, const P* after, SCHAR* buffer, SSHORT* buf_len)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p e r f _ r e p o r t
*
**************************************
*
* Functional description
* Report a common set of parameters.
*
**************************************/
perf_format<P>(before, after, report, buffer, buf_len);
2001-05-23 15:26:42 +02:00
}
static SINT64 get_parameter(const SCHAR** ptr)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e t _ p a r a m e t e r
*
**************************************
*
* Functional description
* Get a parameter (length is encoded), convert to internal form,
* and return.
*
**************************************/
SSHORT l = *(*ptr)++;
2001-05-23 15:26:42 +02:00
l += (*(*ptr)++) << 8;
const SINT64 parameter = isc_portable_integer(reinterpret_cast<const ISC_UCHAR*>(*ptr), l);
2001-05-23 15:26:42 +02:00
*ptr += l;
return parameter;
}
#ifndef HAVE_TIMES
static void times(struct tms* buffer)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* t i m e s
*
**************************************
*
* Functional description
* Emulate the good old unix call "times". Only both with user time.
*
**************************************/
buffer->tms_utime = clock();
}
#endif
int API_ROUTINE perf_format(const PERF* before, const PERF* after,
const SCHAR* string, SCHAR* buffer, SSHORT* buf_len)
{
return perf_format<PERF>(before, after, string, buffer, buf_len);
}
int API_ROUTINE perf64_format(const PERF64* before, const PERF64* after,
const SCHAR* string, SCHAR* buffer, SSHORT* buf_len)
{
return perf_format<PERF64>(before, after, string, buffer, buf_len);
}
void API_ROUTINE perf_get_info(FB_API_HANDLE* handle, PERF* perf)
{
perf_get_info<PERF>(handle, perf);
}
void API_ROUTINE perf64_get_info(FB_API_HANDLE* handle, PERF64* perf)
{
perf_get_info<PERF64>(handle, perf);
}
void API_ROUTINE perf_report(const PERF* before, const PERF* after, SCHAR* buffer, SSHORT* buf_len)
{
perf_report<PERF>(before, after, buffer, buf_len);
}
void API_ROUTINE perf64_report(const PERF64* before, const PERF64* after, SCHAR* buffer, SSHORT* buf_len)
{
perf_report<PERF64>(before, after, buffer, buf_len);
}