Browse code

Add some performance measurement code.

Default off, activated by --dev-performance, and always on in c4w.

Török Edvin authored on 2011/02/15 02:19:20
Showing 16 changed files
... ...
@@ -383,6 +383,9 @@
383 383
 /* Define to 1 if you have the <sys/stat.h> header file. */
384 384
 #undef HAVE_SYS_STAT_H
385 385
 
386
+/* Define to 1 if you have the <sys/times.h> header file. */
387
+#undef HAVE_SYS_TIMES_H
388
+
386 389
 /* Define to 1 if you have the <sys/types.h> header file. */
387 390
 #undef HAVE_SYS_TYPES_H
388 391
 
... ...
@@ -630,6 +630,9 @@ int scanmanager(const struct optstruct *opts)
630 630
 	options |= CL_SCAN_INTERNAL_COLLECT_SHA;
631 631
 #endif
632 632
 
633
+    if(optget(opts, "dev-performance")->enabled)
634
+	options |= CL_SCAN_PERFORMANCE_INFO;
635
+
633 636
     if(optget(opts, "detect-structured")->enabled) {
634 637
 	options |= CL_SCAN_STRUCTURED;
635 638
 
... ...
@@ -13341,7 +13341,7 @@ GPERF=${GPERF-"${am_missing_run}gperf"}
13341 13341
 
13342 13342
 
13343 13343
 
13344
-for ac_header in stdint.h unistd.h sys/int_types.h dlfcn.h inttypes.h sys/inttypes.h memory.h ndir.h stdlib.h strings.h string.h sys/mman.h sys/param.h sys/stat.h sys/types.h malloc.h poll.h limits.h sys/filio.h sys/uio.h termios.h stdbool.h pwd.h grp.h
13344
+for ac_header in stdint.h unistd.h sys/int_types.h dlfcn.h inttypes.h sys/inttypes.h sys/times.h memory.h ndir.h stdlib.h strings.h string.h sys/mman.h sys/param.h sys/stat.h sys/types.h malloc.h poll.h limits.h sys/filio.h sys/uio.h termios.h stdbool.h pwd.h grp.h
13345 13345
 do :
13346 13346
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
13347 13347
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
... ...
@@ -408,7 +408,7 @@ AM_CONDITIONAL([VERSIONSCRIPT], test "x$ac_cv_ld_version_script" = "xyes")
408 408
 AM_MISSING_PROG(GPERF, gperf)
409 409
 AC_SUBST(GPERF)
410 410
 
411
-AC_CHECK_HEADERS([stdint.h unistd.h sys/int_types.h dlfcn.h inttypes.h sys/inttypes.h memory.h ndir.h stdlib.h strings.h string.h sys/mman.h sys/param.h sys/stat.h sys/types.h malloc.h poll.h limits.h sys/filio.h sys/uio.h termios.h stdbool.h pwd.h grp.h])
411
+AC_CHECK_HEADERS([stdint.h unistd.h sys/int_types.h dlfcn.h inttypes.h sys/inttypes.h sys/times.h memory.h ndir.h stdlib.h strings.h string.h sys/mman.h sys/param.h sys/stat.h sys/types.h malloc.h poll.h limits.h sys/filio.h sys/uio.h termios.h stdbool.h pwd.h grp.h])
412 412
 AC_CHECK_HEADER([syslog.h],AC_DEFINE([USE_SYSLOG],1,[use syslog]),)
413 413
 
414 414
 AC_TYPE_OFF_T
... ...
@@ -68,7 +68,7 @@ target_triplet = @target@
68 68
 
69 69
 subdir = libclamav
70 70
 DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
71
-	$(srcdir)/Makefile.in
71
+	$(srcdir)/Makefile.in COPYING
72 72
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
73 73
 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
74 74
 	$(top_srcdir)/m4/argz.m4 \
... ...
@@ -1624,6 +1624,8 @@ int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, stru
1624 1624
 	cli_dbgmsg("bytecode triggered but running bytecodes is disabled\n");
1625 1625
 	return CL_SUCCESS;
1626 1626
     }
1627
+    if (cctx)
1628
+	cli_event_time_start(cctx->perf, PERFT_BYTECODE);
1627 1629
     ctx->env = &bcs->env;
1628 1630
     context_safe(ctx);
1629 1631
     if (test_mode) {
... ...
@@ -1736,6 +1738,8 @@ int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, stru
1736 1736
     }
1737 1737
     cli_events_free(jit_ev);
1738 1738
     cli_events_free(interp_ev);
1739
+    if (cctx)
1740
+	cli_event_time_stop(cctx->perf, PERFT_BYTECODE);
1739 1741
     return ret;
1740 1742
 }
1741 1743
 
... ...
@@ -119,6 +119,7 @@ typedef enum {
119 119
 #define CL_SCAN_HEURISTIC_PRECEDENCE    0x80000
120 120
 #define CL_SCAN_BLOCKMACROS		0x100000
121 121
 
122
+#define CL_SCAN_PERFORMANCE_INFO        0x40000000 /* collect performance timings */
122 123
 #define CL_SCAN_INTERNAL_COLLECT_SHA    0x80000000 /* Enables hash output in sha-collect builds - for internal use only */
123 124
 
124 125
 /* recommended scan settings */
... ...
@@ -150,8 +150,10 @@ void cli_event_int(cli_events_t *ctx, unsigned id, uint64_t arg)
150 150
     switch (ev->multiple) {
151 151
 	case multiple_last:
152 152
 	    ev->u.v_int = arg;
153
+	    ev->count++;
153 154
 	    break;
154 155
 	case multiple_sum:
156
+	    ev->count++;
155 157
 	    ev->u.v_int += arg;
156 158
 	    break;
157 159
 	case multiple_chain:
... ...
@@ -176,6 +178,24 @@ void cli_event_time_start(cli_events_t *ctx, unsigned id)
176 176
     }
177 177
     gettimeofday(&tv, NULL);
178 178
     ev->u.v_int -= ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
179
+    ev->count++;
180
+}
181
+
182
+void cli_event_time_nested_start(cli_events_t *ctx, unsigned id, unsigned nestedid)
183
+{
184
+    struct timeval tv;
185
+    struct cli_event *ev = get_event(ctx, id);
186
+    struct cli_event *evnested = get_event(ctx, nestedid);
187
+    if (!ev || !evnested)
188
+	return;
189
+    if (ev->type != ev_time || evnested->type != ev_time) {
190
+	cli_event_error_str(ctx, "cli_event_time* must be called with ev_time type");
191
+	return;
192
+    }
193
+    gettimeofday(&tv, NULL);
194
+    ev->u.v_int -= ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
195
+    ev->u.v_int += evnested->u.v_int;
196
+    ev->count++;
179 197
 }
180 198
 
181 199
 void cli_event_time_stop(cli_events_t *ctx, unsigned id)
... ...
@@ -192,6 +212,22 @@ void cli_event_time_stop(cli_events_t *ctx, unsigned id)
192 192
     ev->u.v_int += ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
193 193
 }
194 194
 
195
+void cli_event_time_nested_stop(cli_events_t *ctx, unsigned id, unsigned nestedid)
196
+{
197
+    struct timeval tv;
198
+    struct cli_event *ev = get_event(ctx, id);
199
+    struct cli_event *evnested = get_event(ctx, nestedid);
200
+    if (!ev || !evnested)
201
+	return;
202
+    if (ev->type != ev_time || evnested->type != ev_time) {
203
+	cli_event_error_str(ctx, "cli_event_time* must be called with ev_time type");
204
+	return;
205
+    }
206
+    gettimeofday(&tv, NULL);
207
+    ev->u.v_int += ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
208
+    ev->u.v_int -= evnested->u.v_int;
209
+}
210
+
195 211
 static void event_string(cli_events_t *ctx, struct cli_event *ev, const char *str)
196 212
 {
197 213
     if (!str)
... ...
@@ -74,7 +74,8 @@ void cli_event_data(cli_events_t *ctx, unsigned id, const void* data, uint32_t l
74 74
 void cli_event_fastdata(cli_events_t *ctx, unsigned id, const void *data, uint32_t len);
75 75
 
76 76
 void cli_event_time_start(cli_events_t *ctx, unsigned id);
77
-void cli_event_time_stop(cli_events_t *ctx, unsigned id);
77
+void cli_event_time_nested_start(cli_events_t *ctx, unsigned id, unsigned nestedid);
78
+void cli_event_time_nested_stop(cli_events_t *ctx, unsigned id, unsigned nestedid);
78 79
 
79 80
 /* event_count is implemented as ev_int, with ev_multiple_sum multiple */
80 81
 void cli_event_count(cli_events_t *ctx, unsigned id);
... ...
@@ -99,4 +100,22 @@ int cli_event_diff_all(cli_events_t *ctx1, cli_events_t *ctx2, compare_filter_t
99 99
 /* returns whether the given context had errors */
100 100
 int cli_event_errors(cli_events_t *ctx);
101 101
 
102
+enum perfev {
103
+    PERFT_SCAN,
104
+    PERFT_PRECB,
105
+    PERFT_POSTCB,
106
+    PERFT_CACHE,
107
+    PERFT_FT,
108
+    PERFT_CONTAINER,
109
+    PERFT_SCRIPT,
110
+    PERFT_PE,
111
+    PERFT_RAW,
112
+    PERFT_RAWTYPENO,
113
+    PERFT_MAP,
114
+    PERFT_BYTECODE,
115
+    PERFT_KTIME,
116
+    PERFT_UTIME,
117
+    PERFT_LAST
118
+};
119
+
102 120
 #endif
... ...
@@ -43,6 +43,7 @@
43 43
 #include "regex/regex.h"
44 44
 #include "bytecode.h"
45 45
 #include "bytecode_api.h"
46
+#include "events.h"
46 47
 
47 48
 /*
48 49
  * CL_FLEVEL is the signature f-level specific to the current code and
... ...
@@ -125,6 +126,7 @@ typedef struct cli_ctx_tag {
125 125
     fmap_t **fmap;
126 126
     bitset_t* hook_lsig_matches;
127 127
     void *cb_ctx;
128
+    cli_events_t* perf;
128 129
 #ifdef HAVE__INTERNAL__SHA_COLLECT
129 130
     char entry_filename[2048];
130 131
     int sha_collect;
... ...
@@ -39,6 +39,9 @@
39 39
 #endif
40 40
 #include <fcntl.h>
41 41
 #include <dirent.h>
42
+#ifdef HAVE_SYS_TIMES_H
43
+#include <sys/times.h>
44
+#endif
42 45
 
43 46
 #define DCONF_ARCH  ctx->dconf->archive
44 47
 #define DCONF_DOC   ctx->dconf->doc
... ...
@@ -1723,6 +1726,150 @@ static int cli_scanembpe(cli_ctx *ctx, off_t offset)
1723 1723
     return CL_CLEAN;
1724 1724
 }
1725 1725
 
1726
+
1727
+#if defined(_WIN32) || defined(C_LINUX)
1728
+#define PERF_MEASURE
1729
+#endif
1730
+
1731
+#ifdef PERF_MEASURE
1732
+
1733
+static struct {
1734
+    enum perfev id;
1735
+    const char *name;
1736
+    enum ev_type type;
1737
+} perf_events[] = {
1738
+    {PERFT_SCAN, "full scan", ev_time},
1739
+    {PERFT_PRECB, "prescan cb", ev_time},
1740
+    {PERFT_POSTCB, "postscan cb", ev_time},
1741
+    {PERFT_CACHE, "cache", ev_time},
1742
+    {PERFT_FT, "filetype", ev_time},
1743
+    {PERFT_CONTAINER, "container", ev_time},
1744
+    {PERFT_SCRIPT, "script", ev_time},
1745
+    {PERFT_PE, "pe", ev_time},
1746
+    {PERFT_RAW, "raw", ev_time},
1747
+    {PERFT_RAWTYPENO, "raw container", ev_time},
1748
+    {PERFT_MAP, "map", ev_time},
1749
+    {PERFT_BYTECODE,"bytecode", ev_time},
1750
+    {PERFT_KTIME,"kernel", ev_int},
1751
+    {PERFT_UTIME,"user", ev_int}
1752
+};
1753
+
1754
+static void get_thread_times(uint64_t *kt, uint64_t *ut)
1755
+{
1756
+#ifdef _WIN32
1757
+    LPFILETIME c,e,k,u;
1758
+    ULARGE_INTEGER kl,ul;
1759
+    if (!GetThreadTimes(GetCurrentThread(), &c, &e, &k, &u)) {
1760
+	*kt = *ut = 0;
1761
+	return;
1762
+    }
1763
+    kl.LowPart = k.dwLowDateTime;
1764
+    kl.HighPart = k.dwHighDateTime;
1765
+    ul.LowPart = u.dwLowDateTime;
1766
+    ul.HighPart = u.dwHighDateTime;
1767
+    *kt = kl.QuadPart / 10;
1768
+    *ut = ul.QuadPart / 10;
1769
+#else
1770
+    struct tms tbuf;
1771
+    if (times(&tbuf) != -1) {
1772
+	clock_t tck = sysconf(_SC_CLK_TCK);
1773
+	*kt = 1000000*tbuf.tms_stime / tck;
1774
+	*ut = 1000000*tbuf.tms_utime / tck;
1775
+    } else {
1776
+	*kt = *ut = 0;
1777
+    }
1778
+#endif
1779
+}
1780
+
1781
+static inline void perf_init(cli_ctx *ctx)
1782
+{
1783
+    uint64_t kt,ut;
1784
+    unsigned i;
1785
+
1786
+    if (!(ctx->options & CL_SCAN_PERFORMANCE_INFO))
1787
+	return;
1788
+
1789
+    ctx->perf = cli_events_new(PERFT_LAST);
1790
+    for (i=0;i<sizeof(perf_events)/sizeof(perf_events[0]);i++) {
1791
+	if (cli_event_define(ctx->perf, perf_events[i].id, perf_events[i].name,
1792
+			     perf_events[i].type, multiple_sum) == -1)
1793
+	    continue;
1794
+    }
1795
+    cli_event_time_start(ctx->perf, PERFT_SCAN);
1796
+    get_thread_times(&kt, &ut);
1797
+    cli_event_int(ctx->perf, PERFT_KTIME, -kt);
1798
+    cli_event_int(ctx->perf, PERFT_UTIME, -ut);
1799
+}
1800
+
1801
+static inline void perf_done(cli_ctx* ctx)
1802
+{
1803
+    char timestr[512];
1804
+    char *p;
1805
+    unsigned i;
1806
+    uint64_t kt,ut;
1807
+    cli_events_t *perf = ctx->perf;
1808
+
1809
+    if (!perf)
1810
+	return;
1811
+
1812
+    p = timestr;
1813
+    char *pend = timestr + sizeof(timestr) - 1;
1814
+    *pend = 0;
1815
+
1816
+    cli_event_time_stop(perf, PERFT_SCAN);
1817
+    get_thread_times(&kt, &ut);
1818
+    cli_event_int(perf, PERFT_KTIME, kt);
1819
+    cli_event_int(perf, PERFT_UTIME, ut);
1820
+
1821
+    for (i=0;i<sizeof(perf_events)/sizeof(perf_events[0]);i++) {
1822
+	union ev_val val;
1823
+	unsigned count;
1824
+
1825
+	cli_event_get(perf, perf_events[i].id, &val, &count);
1826
+	if (p < pend)
1827
+	    p += snprintf(p, pend - p, "%s: %d.%03ums, ", perf_events[i].name,
1828
+			  (signed)(val.v_int / 1000),
1829
+			  (unsigned)(val.v_int % 1000));
1830
+    }
1831
+    *p = 0;
1832
+    cli_infomsg(ctx, "performance: %s\n", timestr);
1833
+
1834
+
1835
+    cli_events_free(perf);
1836
+    ctx->perf = NULL;
1837
+}
1838
+
1839
+static inline void perf_start(cli_ctx* ctx, int id)
1840
+{
1841
+    cli_event_time_start(ctx->perf, id);
1842
+}
1843
+
1844
+static inline void perf_stop(cli_ctx* ctx, int id)
1845
+{
1846
+    cli_event_time_stop(ctx->perf, id);
1847
+}
1848
+
1849
+static inline void perf_nested_start(cli_ctx* ctx, int id, int nestedid)
1850
+{
1851
+    cli_event_time_nested_start(ctx->perf, id, nestedid);
1852
+}
1853
+
1854
+static inline void perf_nested_stop(cli_ctx* ctx, int id, int nestedid)
1855
+{
1856
+    cli_event_time_nested_stop(ctx->perf, id, nestedid);
1857
+}
1858
+
1859
+
1860
+#else
1861
+static inline void perf_init(cli_events_t **perf) {}
1862
+static inline void perf_start(cli_ctx* ctx, int id){}
1863
+static inline void perf_stop(cli_ctx* ctx, int id){}
1864
+static inline void perf_nested_start(cli_ctx* ctx, int id){}
1865
+static inline void perf_nested_stop(cli_ctx* ctx, int id){}
1866
+static inline void perf_done(cli_events_t **perf) {}
1867
+#endif
1868
+
1869
+
1726 1870
 static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_t *dettype, unsigned char *refhash)
1727 1871
 {
1728 1872
 	int ret = CL_CLEAN, nret = CL_CLEAN;
... ...
@@ -1738,12 +1885,15 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_
1738 1738
     if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
1739 1739
         return CL_EMAXREC;
1740 1740
 
1741
+    perf_start(ctx, PERFT_RAW);
1741 1742
     if(typercg)
1742 1743
 	acmode |= AC_SCAN_FT;
1743 1744
 
1744 1745
     ret = cli_fmap_scandesc(ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode, NULL, refhash);
1746
+    perf_stop(ctx, PERFT_RAW);
1745 1747
 
1746 1748
     if(ret >= CL_TYPENO) {
1749
+	perf_nested_start(ctx, PERFT_RAWTYPENO, PERFT_SCAN);
1747 1750
 	ctx->recursion++;
1748 1751
 	if(nret != CL_VIRUS) {
1749 1752
 	    lastzip = lastrar = 0xdeadbeef;
... ...
@@ -1880,6 +2030,7 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_
1880 1880
 	    default:
1881 1881
 		break;
1882 1882
 	}
1883
+	perf_nested_stop(ctx, PERFT_RAWTYPENO, PERFT_SCAN);
1883 1884
 	ctx->recursion--;
1884 1885
 	ret = nret;
1885 1886
     }
... ...
@@ -1915,20 +2066,24 @@ static void emax_reached(cli_ctx *ctx) {
1915 1915
 #define ret_from_magicscan(retcode) do {							\
1916 1916
     cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__);			\
1917 1917
     if(ctx->engine->cb_post_scan) {								\
1918
+	perf_start(ctx, PERFT_POSTCB);                                                         \
1918 1919
 	switch(ctx->engine->cb_post_scan(desc, retcode, retcode == CL_VIRUS && ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx)) {		\
1919 1920
 	case CL_BREAK:										\
1920 1921
 	    cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n");			\
1922
+	    perf_stop(ctx, PERFT_POSTCB);                                                      \
1921 1923
 	    return CL_CLEAN;									\
1922 1924
 	case CL_VIRUS:										\
1923 1925
 	    cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n");			\
1924 1926
 	    if(ctx->virname)									\
1925 1927
 		*ctx->virname = "Detected.By.Callback";						\
1928
+	    perf_stop(ctx, PERFT_POSTCB);                                                      \
1926 1929
 	    return CL_VIRUS;									\
1927 1930
 	case CL_CLEAN:										\
1928 1931
 	    break;										\
1929 1932
 	default:										\
1930 1933
 	    cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n");	\
1931 1934
 	}											\
1935
+	perf_stop(ctx, PERFT_POSTCB);                                                          \
1932 1936
     }\
1933 1937
     return retcode;										\
1934 1938
     } while(0)
... ...
@@ -1981,18 +2136,23 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
1981 1981
     }
1982 1982
 
1983 1983
     ctx->fmap++;
1984
+    perf_start(ctx, PERFT_MAP);
1984 1985
     if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
1985 1986
 	cli_errmsg("CRITICAL: fmap() failed\n");
1986 1987
 	ctx->fmap--;
1988
+	perf_stop(ctx, PERFT_MAP);
1987 1989
 	ret_from_magicscan(CL_EMEM);
1988 1990
     }
1991
+    perf_stop(ctx, PERFT_MAP);
1989 1992
 
1990 1993
     if(ctx->engine->cb_pre_scan) {
1994
+	perf_start(ctx, PERFT_PRECB);
1991 1995
 	switch(ctx->engine->cb_pre_scan(desc, ctx->cb_ctx)) {
1992 1996
 	case CL_BREAK:
1993 1997
 	    cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n");
1994 1998
 	    funmap(*ctx->fmap);
1995 1999
 	    ctx->fmap--;
2000
+	    perf_stop(ctx, PERFT_PRECB);
1996 2001
 	    ret_from_magicscan(CL_CLEAN);
1997 2002
 	case CL_VIRUS:
1998 2003
 	    cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n");
... ...
@@ -2000,19 +2160,24 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2000 2000
 		*ctx->virname = "Detected.By.Callback";
2001 2001
 	    funmap(*ctx->fmap);
2002 2002
 	    ctx->fmap--;
2003
+	    perf_stop(ctx, PERFT_PRECB);
2003 2004
 	    ret_from_magicscan(CL_VIRUS);
2004 2005
 	case CL_CLEAN:
2005 2006
 	    break;
2006 2007
 	default:
2007 2008
 	    cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n");
2008 2009
 	}
2010
+	perf_stop(ctx, PERFT_PRECB);
2009 2011
     }
2010 2012
 
2013
+    perf_start(ctx, PERFT_CACHE);
2011 2014
     if(cache_check(hash, ctx) == CL_CLEAN) {
2012 2015
 	funmap(*ctx->fmap);
2013 2016
 	ctx->fmap--;
2017
+	perf_stop(ctx, PERFT_CACHE);
2014 2018
 	ret_from_magicscan(CL_CLEAN);
2015 2019
     }
2020
+    perf_stop(ctx, PERFT_CACHE);
2016 2021
     hashed_size = (*ctx->fmap)->len;
2017 2022
     old_hook_lsig_matches = ctx->hook_lsig_matches;
2018 2023
     ctx->hook_lsig_matches = NULL;
... ...
@@ -2038,8 +2203,10 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2038 2038
 	ret_from_magicscan(ret);
2039 2039
     }
2040 2040
 
2041
+    perf_start(ctx, PERFT_FT);
2041 2042
     if(type == CL_TYPE_ANY)
2042 2043
 	type = cli_filetype2(*ctx->fmap, ctx->engine); /* FIXMEFMAP: port to fmap */
2044
+    perf_stop(ctx, PERFT_FT);
2043 2045
     if(type == CL_TYPE_ERROR) {
2044 2046
 	cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
2045 2047
 	funmap(*ctx->fmap);
... ...
@@ -2073,6 +2240,7 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2073 2073
     }
2074 2074
 
2075 2075
     ctx->recursion++;
2076
+    perf_nested_start(ctx, PERFT_CONTAINER, PERFT_SCAN);
2076 2077
     switch(type) {
2077 2078
 	case CL_TYPE_IGNORED:
2078 2079
 	    break;
... ...
@@ -2306,6 +2474,7 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2306 2306
 	default:
2307 2307
 	    break;
2308 2308
     }
2309
+    perf_nested_stop(ctx, PERFT_CONTAINER, PERFT_SCAN);
2309 2310
     ctx->recursion--;
2310 2311
     ctx->container_type = current_container_type;
2311 2312
     ctx->container_size = current_container_size;
... ...
@@ -2347,22 +2516,26 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2347 2347
 	case CL_TYPE_TEXT_UTF16BE:
2348 2348
 	case CL_TYPE_TEXT_UTF16LE:
2349 2349
 	case CL_TYPE_TEXT_UTF8:
2350
+	    perf_nested_start(ctx, PERFT_SCRIPT, PERFT_SCAN);
2350 2351
 	    if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
2351 2352
 	        ret = cli_scanscript(ctx);
2352 2353
 	    if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX) && ret != CL_VIRUS && (ctx->container_type == CL_TYPE_MAIL || dettype == CL_TYPE_MAIL)) {
2353 2354
 		lseek(desc, 0, SEEK_SET);
2354 2355
 		ret = cli_scandesc(desc, ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR, NULL);
2355 2356
 	    }
2357
+	    perf_nested_stop(ctx, PERFT_SCRIPT, PERFT_SCAN);
2356 2358
 	    break;
2357 2359
 	/* Due to performance reasons all executables were first scanned
2358 2360
 	 * in raw mode. Now we will try to unpack them
2359 2361
 	 */
2360 2362
 	case CL_TYPE_MSEXE:
2363
+	    perf_nested_start(ctx, PERFT_PE, PERFT_SCAN);
2361 2364
 	    if(SCAN_PE && ctx->dconf->pe) {
2362 2365
 		unsigned int corrupted_input = ctx->corrupted_input;
2363 2366
 		ret = cli_scanpe(ctx);
2364 2367
 		ctx->corrupted_input = corrupted_input;
2365 2368
 	    }
2369
+	    perf_nested_stop(ctx, PERFT_PE, PERFT_SCAN);
2366 2370
 	    break;
2367 2371
 	default:
2368 2372
 	    break;
... ...
@@ -2383,7 +2556,9 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2383 2383
 	case CL_EMAXFILES:
2384 2384
 	    cli_dbgmsg("Descriptor[%d]: %s\n", desc, cl_strerror(ret));
2385 2385
 	case CL_CLEAN:
2386
+	    perf_start(ctx, PERFT_CACHE);
2386 2387
 	    cache_add(hash, hashed_size, ctx);
2388
+	    perf_stop(ctx, PERFT_CACHE);
2387 2389
 	    ret_from_magicscan(CL_CLEAN);
2388 2390
 	default:
2389 2391
 	    ret_from_magicscan(ret);
... ...
@@ -2427,6 +2602,7 @@ int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scan
2427 2427
 	free(ctx.fmap);
2428 2428
 	return CL_EMEM;
2429 2429
     }
2430
+    perf_init(&ctx);
2430 2431
 
2431 2432
 #ifdef HAVE__INTERNAL__SHA_COLLECT
2432 2433
     if(scanoptions & CL_SCAN_INTERNAL_COLLECT_SHA) {
... ...
@@ -2451,6 +2627,7 @@ int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scan
2451 2451
     if(rc == CL_CLEAN && ctx.found_possibly_unwanted)
2452 2452
 	rc = CL_VIRUS;
2453 2453
     cli_logg_unsetup();
2454
+    perf_done(&ctx);
2454 2455
     return rc;
2455 2456
 }
2456 2457
 
... ...
@@ -28,9 +28,6 @@
28 28
 ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 29
 #####
30 30
 
31
-# ClamAV: filter -Werror here
32
-CFLAGS=`echo "@CFLAGS@" | sed -e 's/-Werror[^=-]//'`
33
-
34 31
 ACLOCAL_AMFLAGS = -I m4
35 32
 AUTOMAKE_OPTIONS = foreign
36 33
 AM_CPPFLAGS =
... ...
@@ -140,6 +137,12 @@ CLEANFILES		       += libltdl.la \
140 140
 CLEANFILES	       += $(ltdl_LIBOBJS) $(ltdl_LTLIBOBJS)
141 141
 
142 142
 EXTRA_DIST	       += COPYING.LIB \
143
+			   \
144
+			   \
145
+			   \
146
+			   \
147
+			   \
148
+			   \
143 149
 			  README
144 150
 
145 151
 ## --------------------------- ##
... ...
@@ -154,7 +157,6 @@ EXTRA_DIST	+= argz_.h \
154 154
 # doesn't have one that works with the given compiler.
155 155
 all-local $(lib_OBJECTS): $(ARGZ_H)
156 156
 argz.h: argz_.h
157
-	$(mkinstalldirs) . 
158 157
 	cp $(srcdir)/argz_.h $@-t
159 158
 	mv $@-t $@
160 159
 MOSTLYCLEANFILES += argz.h \
... ...
@@ -201,9 +201,7 @@ BUILD_CONFIGURE_FLAGS = @BUILD_CONFIGURE_FLAGS@
201 201
 CC = @CC@
202 202
 CCDEPMODE = @CCDEPMODE@
203 203
 CFGDIR = @CFGDIR@
204
-
205
-# ClamAV: filter -Werror here
206
-CFLAGS = `echo "@CFLAGS@" | sed -e 's/-Werror[^=-]//'`
204
+CFLAGS = @CFLAGS@
207 205
 CHECK_CPPFLAGS = @CHECK_CPPFLAGS@
208 206
 CHECK_LIBS = @CHECK_LIBS@
209 207
 CLAMAVGROUP = @CLAMAVGROUP@
... ...
@@ -962,7 +960,6 @@ uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES \
962 962
 # doesn't have one that works with the given compiler.
963 963
 all-local $(lib_OBJECTS): $(ARGZ_H)
964 964
 argz.h: argz_.h
965
-	$(mkinstalldirs) . 
966 965
 	cp $(srcdir)/argz_.h $@-t
967 966
 	mv $@-t $@
968 967
 
... ...
@@ -342,6 +342,7 @@ const struct clam_option __clam_options[] = {
342 342
 #ifdef HAVE__INTERNAL__SHA_COLLECT
343 343
     { "DevCollectHashes", "dev-collect-hashes", 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, FLAG_HIDDEN, OPT_CLAMD | OPT_CLAMSCAN, "", "" },
344 344
 #endif
345
+    { "DevPerformance", "dev-performance", 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, FLAG_HIDDEN, OPT_CLAMD | OPT_CLAMSCAN, "", "" },
345 346
     { "DevLiblog", "dev-liblog", 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, FLAG_HIDDEN, OPT_CLAMD, "", "" },
346 347
 
347 348
     /* Freshclam-only entries */
... ...
@@ -385,6 +385,9 @@
385 385
 /* Define to 1 if you have the <sys/stat.h> header file. */
386 386
 #define HAVE_SYS_STAT_H 1
387 387
 
388
+/* Define to 1 if you have the <sys/times.h> header file. */
389
+/* #undef HAVE_SYS_TIMES_H */
390
+
388 391
 /* Define to 1 if you have the <sys/types.h> header file. */
389 392
 #define HAVE_SYS_TYPES_H 1
390 393
 
... ...
@@ -502,7 +505,7 @@
502 502
 /* #undef USE_SYSLOG */
503 503
 
504 504
 /* Version number of package */
505
-#define VERSION "clamav-0.97"
505
+#define VERSION "devel-clamav-0.97-17-ge0aab5d"
506 506
 
507 507
 /* Version suffix for package */
508 508
 #define VERSION_SUFFIX ""
... ...
@@ -467,7 +467,7 @@ int CLAMAPI Scan_CreateInstance(CClamAVScanner **ppScanner) {
467 467
 	FAIL(CL_EMEM, "add_instance failed");
468 468
     }
469 469
     unlock_engine();
470
-    inst->scanopts = CL_SCAN_STDOPT;
470
+    inst->scanopts = CL_SCAN_STDOPT | CL_SCAN_PERFORMANCE_INFO;
471 471
     *ppScanner = (CClamAVScanner *)inst;
472 472
     logg("Created new instance %p\n", inst);
473 473
     WIN();