зеркало из https://github.com/mozilla/pjs.git
Made nsTraceRefcnt output write to streams.
This commit is contained in:
Родитель
880d55f658
Коммит
9d3362a93a
|
@ -23,6 +23,9 @@
|
|||
#include "prlog.h"
|
||||
#include "plstr.h"
|
||||
#include <stdlib.h>
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIFileStream.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
@ -168,7 +171,8 @@ public:
|
|||
static PRIntn DumpNewEntry(PLHashEntry *he, PRIntn i, void *arg) {
|
||||
BloatEntry* entry = (BloatEntry*)he->value;
|
||||
if (entry) {
|
||||
entry->Dump(i, (FILE*)arg, &entry->mNewStats);
|
||||
nsresult rv = entry->Dump(i, (nsIOutputStream*)arg, &entry->mNewStats);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Dump failed");
|
||||
entry->Accumulate();
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
|
@ -178,7 +182,8 @@ public:
|
|||
BloatEntry* entry = (BloatEntry*)he->value;
|
||||
if (entry) {
|
||||
entry->Accumulate();
|
||||
entry->Dump(i, (FILE*)arg, &entry->mAllStats);
|
||||
nsresult rv = entry->Dump(i, (nsIOutputStream*)arg, &entry->mAllStats);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Dump failed");
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
@ -210,15 +215,31 @@ public:
|
|||
(mNewStats.mCreates != mNewStats.mDestroys));
|
||||
}
|
||||
|
||||
static void PrintDumpHeader(FILE* out, const char* msg) {
|
||||
fprintf(out, " %s -- Bloaty: Refcounting and Memory Bloat Statistics\n", msg);
|
||||
fprintf(out, " |<------class------>|<--------------References-------------->|<----------------Objects---------------->|<------Size----->|\n");
|
||||
fprintf(out, " Rem Total Mean StdDev Rem Total Mean StdDev Per-Class Rem\n");
|
||||
static nsresult PrintDumpHeader(nsIOutputStream* out, const char* msg) {
|
||||
nsresult rv;
|
||||
char buf[256];
|
||||
PRUint32 cnt, writeCnt;
|
||||
cnt = PR_snprintf(buf, 256,
|
||||
" %s -- Bloaty: Refcounting and Memory Bloat Statistics\n", msg);
|
||||
rv = out->Write(buf, cnt, &writeCnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ASSERTION(cnt == writeCnt, "failed to write all data");
|
||||
cnt = PR_snprintf(buf, 256,
|
||||
" |<------class------>|<--------------References-------------->|<----------------Objects---------------->|<------Size----->|\n");
|
||||
rv = out->Write(buf, cnt, &writeCnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ASSERTION(cnt == writeCnt, "failed to write all data");
|
||||
cnt = PR_snprintf(buf, 256,
|
||||
" Rem Total Mean StdDev Rem Total Mean StdDev Per-Class Rem\n");
|
||||
rv = out->Write(buf, cnt, &writeCnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ASSERTION(cnt == writeCnt, "failed to write all data");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void Dump(PRIntn i, FILE* fp, nsTraceRefcntStats* stats) {
|
||||
nsresult Dump(PRIntn i, nsIOutputStream* out, nsTraceRefcntStats* stats) {
|
||||
if (gDumpLeaksOnly && !HaveLeaks()) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
double nRefs = stats->mAddRefs + stats->mReleases;
|
||||
double meanRefs = nRefs != 0.0 ? stats->mRefsOutstandingTotal / nRefs : 0.0;
|
||||
|
@ -241,19 +262,25 @@ public:
|
|||
stats->mCreates != 0 ||
|
||||
meanObjs != 0 ||
|
||||
stddevObjs != 0) {
|
||||
fprintf(fp, "%4d %-20.20s %8d %8d (%8.2f +/- %8.2f) %8d %8d (%8.2f +/- %8.2f) %8d %8d\n",
|
||||
i, mClassName,
|
||||
(stats->mAddRefs - stats->mReleases),
|
||||
stats->mAddRefs,
|
||||
meanRefs,
|
||||
stddevRefs,
|
||||
(stats->mCreates - stats->mDestroys),
|
||||
stats->mCreates,
|
||||
meanObjs,
|
||||
stddevObjs,
|
||||
mClassSize,
|
||||
(stats->mCreates - stats->mDestroys) * mClassSize);
|
||||
char buf[256];
|
||||
PRUint32 cnt, writeCnt;
|
||||
cnt = PR_snprintf(buf, 256, "%4d %-20.20s %8d %8d (%8.2f +/- %8.2f) %8d %8d (%8.2f +/- %8.2f) %8d %8d\n",
|
||||
i, mClassName,
|
||||
(stats->mAddRefs - stats->mReleases),
|
||||
stats->mAddRefs,
|
||||
meanRefs,
|
||||
stddevRefs,
|
||||
(stats->mCreates - stats->mDestroys),
|
||||
stats->mCreates,
|
||||
meanObjs,
|
||||
stddevObjs,
|
||||
mClassSize,
|
||||
(stats->mCreates - stats->mDestroys) * mClassSize);
|
||||
nsresult rv = out->Write(buf, cnt, &writeCnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ASSERTION(cnt == writeCnt, "failed to write all data");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -296,12 +323,13 @@ GetBloatEntry(const char* aTypeName, PRUint32 aInstanceSize)
|
|||
|
||||
#endif /* NS_BUILD_REFCNT_LOGGING */
|
||||
|
||||
void
|
||||
nsTraceRefcnt::DumpNewStatistics(FILE* out)
|
||||
nsresult
|
||||
nsTraceRefcnt::DumpStatistics(StatisticsType type,
|
||||
nsIOutputStream* out)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
if (!gTrackBloat || !gBloatView) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
LOCK_TRACELOG();
|
||||
|
@ -309,30 +337,37 @@ nsTraceRefcnt::DumpNewStatistics(FILE* out)
|
|||
printf("Bloaty: Only dumping data about objects that leaked\n");
|
||||
}
|
||||
|
||||
BloatEntry::PrintDumpHeader(out, "NEW RESULTS");
|
||||
PL_HashTableDump(gBloatView, BloatEntry::DumpNewEntry, out);
|
||||
|
||||
UNLOCK_TRACELOG();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsTraceRefcnt::DumpAllStatistics(FILE* out)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
if (!gTrackBloat || !gBloatView) {
|
||||
return;
|
||||
PRBool wasLogging = gLogging;
|
||||
gLogging = PR_FALSE; // turn off logging for this method
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIOutputStream> outStr = dont_QueryInterface(out);
|
||||
if (out == nsnull) {
|
||||
nsCOMPtr<nsISupports> outSupports;
|
||||
rv = NS_NewOutputConsoleStream(getter_AddRefs(outSupports));
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
outStr = do_QueryInterface(outSupports, &rv);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
}
|
||||
|
||||
LOCK_TRACELOG();
|
||||
if (gDumpLeaksOnly) {
|
||||
printf("Bloaty: Only dumping data about objects that leaked\n");
|
||||
PRIntn (*dump)(PLHashEntry *he, PRIntn i, void *arg);
|
||||
const char* msg;
|
||||
if (type == NEW_STATS) {
|
||||
dump = BloatEntry::DumpNewEntry;
|
||||
msg = "NEW RESULTS";
|
||||
}
|
||||
else {
|
||||
dump = BloatEntry::DumpAllEntry;
|
||||
msg = "ALL RESULTS";
|
||||
}
|
||||
rv = BloatEntry::PrintDumpHeader(outStr, msg);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
PL_HashTableEnumerateEntries(gBloatView, dump, outStr);
|
||||
|
||||
BloatEntry::PrintDumpHeader(out, "ALL RESULTS");
|
||||
PL_HashTableDump(gBloatView, BloatEntry::DumpAllEntry, out);
|
||||
|
||||
done:
|
||||
gLogging = wasLogging;
|
||||
UNLOCK_TRACELOG();
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#define nsTraceRefcnt_h___
|
||||
|
||||
#include "nsCom.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// Normaly, the implementation of NS_LOG_ADDREF and NS_LOG_RELEASE
|
||||
// will use a stack crawl to determine who called Addref/Release on an
|
||||
|
@ -103,6 +102,8 @@ PR_END_MACRO
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class nsIOutputStream;
|
||||
|
||||
struct nsTraceRefcntStats {
|
||||
nsrefcnt mAddRefs;
|
||||
nsrefcnt mReleases;
|
||||
|
@ -170,10 +171,14 @@ public:
|
|||
static NS_COM void LogDtor(void* aPtr, const char* aTypeName,
|
||||
PRUint32 aInstanceSize);
|
||||
|
||||
static NS_COM void DumpNewStatistics(FILE* out = stdout);
|
||||
|
||||
static NS_COM void DumpAllStatistics(FILE* out = stdout);
|
||||
enum StatisticsType {
|
||||
ALL_STATS,
|
||||
NEW_STATS
|
||||
};
|
||||
|
||||
static NS_COM nsresult DumpStatistics(StatisticsType type = ALL_STATS,
|
||||
nsIOutputStream* out = nsnull);
|
||||
|
||||
static NS_COM void ResetStatistics(void);
|
||||
|
||||
static NS_COM void GatherStatistics(nsTraceRefcntStatFunc aFunc,
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include "prlog.h"
|
||||
#include "plstr.h"
|
||||
#include <stdlib.h>
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIFileStream.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
@ -168,7 +171,8 @@ public:
|
|||
static PRIntn DumpNewEntry(PLHashEntry *he, PRIntn i, void *arg) {
|
||||
BloatEntry* entry = (BloatEntry*)he->value;
|
||||
if (entry) {
|
||||
entry->Dump(i, (FILE*)arg, &entry->mNewStats);
|
||||
nsresult rv = entry->Dump(i, (nsIOutputStream*)arg, &entry->mNewStats);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Dump failed");
|
||||
entry->Accumulate();
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
|
@ -178,7 +182,8 @@ public:
|
|||
BloatEntry* entry = (BloatEntry*)he->value;
|
||||
if (entry) {
|
||||
entry->Accumulate();
|
||||
entry->Dump(i, (FILE*)arg, &entry->mAllStats);
|
||||
nsresult rv = entry->Dump(i, (nsIOutputStream*)arg, &entry->mAllStats);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Dump failed");
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
@ -210,15 +215,31 @@ public:
|
|||
(mNewStats.mCreates != mNewStats.mDestroys));
|
||||
}
|
||||
|
||||
static void PrintDumpHeader(FILE* out, const char* msg) {
|
||||
fprintf(out, " %s -- Bloaty: Refcounting and Memory Bloat Statistics\n", msg);
|
||||
fprintf(out, " |<------class------>|<--------------References-------------->|<----------------Objects---------------->|<------Size----->|\n");
|
||||
fprintf(out, " Rem Total Mean StdDev Rem Total Mean StdDev Per-Class Rem\n");
|
||||
static nsresult PrintDumpHeader(nsIOutputStream* out, const char* msg) {
|
||||
nsresult rv;
|
||||
char buf[256];
|
||||
PRUint32 cnt, writeCnt;
|
||||
cnt = PR_snprintf(buf, 256,
|
||||
" %s -- Bloaty: Refcounting and Memory Bloat Statistics\n", msg);
|
||||
rv = out->Write(buf, cnt, &writeCnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ASSERTION(cnt == writeCnt, "failed to write all data");
|
||||
cnt = PR_snprintf(buf, 256,
|
||||
" |<------class------>|<--------------References-------------->|<----------------Objects---------------->|<------Size----->|\n");
|
||||
rv = out->Write(buf, cnt, &writeCnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ASSERTION(cnt == writeCnt, "failed to write all data");
|
||||
cnt = PR_snprintf(buf, 256,
|
||||
" Rem Total Mean StdDev Rem Total Mean StdDev Per-Class Rem\n");
|
||||
rv = out->Write(buf, cnt, &writeCnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ASSERTION(cnt == writeCnt, "failed to write all data");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void Dump(PRIntn i, FILE* fp, nsTraceRefcntStats* stats) {
|
||||
nsresult Dump(PRIntn i, nsIOutputStream* out, nsTraceRefcntStats* stats) {
|
||||
if (gDumpLeaksOnly && !HaveLeaks()) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
double nRefs = stats->mAddRefs + stats->mReleases;
|
||||
double meanRefs = nRefs != 0.0 ? stats->mRefsOutstandingTotal / nRefs : 0.0;
|
||||
|
@ -241,19 +262,25 @@ public:
|
|||
stats->mCreates != 0 ||
|
||||
meanObjs != 0 ||
|
||||
stddevObjs != 0) {
|
||||
fprintf(fp, "%4d %-20.20s %8d %8d (%8.2f +/- %8.2f) %8d %8d (%8.2f +/- %8.2f) %8d %8d\n",
|
||||
i, mClassName,
|
||||
(stats->mAddRefs - stats->mReleases),
|
||||
stats->mAddRefs,
|
||||
meanRefs,
|
||||
stddevRefs,
|
||||
(stats->mCreates - stats->mDestroys),
|
||||
stats->mCreates,
|
||||
meanObjs,
|
||||
stddevObjs,
|
||||
mClassSize,
|
||||
(stats->mCreates - stats->mDestroys) * mClassSize);
|
||||
char buf[256];
|
||||
PRUint32 cnt, writeCnt;
|
||||
cnt = PR_snprintf(buf, 256, "%4d %-20.20s %8d %8d (%8.2f +/- %8.2f) %8d %8d (%8.2f +/- %8.2f) %8d %8d\n",
|
||||
i, mClassName,
|
||||
(stats->mAddRefs - stats->mReleases),
|
||||
stats->mAddRefs,
|
||||
meanRefs,
|
||||
stddevRefs,
|
||||
(stats->mCreates - stats->mDestroys),
|
||||
stats->mCreates,
|
||||
meanObjs,
|
||||
stddevObjs,
|
||||
mClassSize,
|
||||
(stats->mCreates - stats->mDestroys) * mClassSize);
|
||||
nsresult rv = out->Write(buf, cnt, &writeCnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ASSERTION(cnt == writeCnt, "failed to write all data");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -296,12 +323,13 @@ GetBloatEntry(const char* aTypeName, PRUint32 aInstanceSize)
|
|||
|
||||
#endif /* NS_BUILD_REFCNT_LOGGING */
|
||||
|
||||
void
|
||||
nsTraceRefcnt::DumpNewStatistics(FILE* out)
|
||||
nsresult
|
||||
nsTraceRefcnt::DumpStatistics(StatisticsType type,
|
||||
nsIOutputStream* out)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
if (!gTrackBloat || !gBloatView) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
LOCK_TRACELOG();
|
||||
|
@ -309,30 +337,37 @@ nsTraceRefcnt::DumpNewStatistics(FILE* out)
|
|||
printf("Bloaty: Only dumping data about objects that leaked\n");
|
||||
}
|
||||
|
||||
BloatEntry::PrintDumpHeader(out, "NEW RESULTS");
|
||||
PL_HashTableDump(gBloatView, BloatEntry::DumpNewEntry, out);
|
||||
|
||||
UNLOCK_TRACELOG();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsTraceRefcnt::DumpAllStatistics(FILE* out)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
if (!gTrackBloat || !gBloatView) {
|
||||
return;
|
||||
PRBool wasLogging = gLogging;
|
||||
gLogging = PR_FALSE; // turn off logging for this method
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIOutputStream> outStr = dont_QueryInterface(out);
|
||||
if (out == nsnull) {
|
||||
nsCOMPtr<nsISupports> outSupports;
|
||||
rv = NS_NewOutputConsoleStream(getter_AddRefs(outSupports));
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
outStr = do_QueryInterface(outSupports, &rv);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
}
|
||||
|
||||
LOCK_TRACELOG();
|
||||
if (gDumpLeaksOnly) {
|
||||
printf("Bloaty: Only dumping data about objects that leaked\n");
|
||||
PRIntn (*dump)(PLHashEntry *he, PRIntn i, void *arg);
|
||||
const char* msg;
|
||||
if (type == NEW_STATS) {
|
||||
dump = BloatEntry::DumpNewEntry;
|
||||
msg = "NEW RESULTS";
|
||||
}
|
||||
else {
|
||||
dump = BloatEntry::DumpAllEntry;
|
||||
msg = "ALL RESULTS";
|
||||
}
|
||||
rv = BloatEntry::PrintDumpHeader(outStr, msg);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
PL_HashTableEnumerateEntries(gBloatView, dump, outStr);
|
||||
|
||||
BloatEntry::PrintDumpHeader(out, "ALL RESULTS");
|
||||
PL_HashTableDump(gBloatView, BloatEntry::DumpAllEntry, out);
|
||||
|
||||
done:
|
||||
gLogging = wasLogging;
|
||||
UNLOCK_TRACELOG();
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#define nsTraceRefcnt_h___
|
||||
|
||||
#include "nsCom.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// Normaly, the implementation of NS_LOG_ADDREF and NS_LOG_RELEASE
|
||||
// will use a stack crawl to determine who called Addref/Release on an
|
||||
|
@ -103,6 +102,8 @@ PR_END_MACRO
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class nsIOutputStream;
|
||||
|
||||
struct nsTraceRefcntStats {
|
||||
nsrefcnt mAddRefs;
|
||||
nsrefcnt mReleases;
|
||||
|
@ -170,10 +171,14 @@ public:
|
|||
static NS_COM void LogDtor(void* aPtr, const char* aTypeName,
|
||||
PRUint32 aInstanceSize);
|
||||
|
||||
static NS_COM void DumpNewStatistics(FILE* out = stdout);
|
||||
|
||||
static NS_COM void DumpAllStatistics(FILE* out = stdout);
|
||||
enum StatisticsType {
|
||||
ALL_STATS,
|
||||
NEW_STATS
|
||||
};
|
||||
|
||||
static NS_COM nsresult DumpStatistics(StatisticsType type = ALL_STATS,
|
||||
nsIOutputStream* out = nsnull);
|
||||
|
||||
static NS_COM void ResetStatistics(void);
|
||||
|
||||
static NS_COM void GatherStatistics(nsTraceRefcntStatFunc aFunc,
|
||||
|
|
|
@ -82,7 +82,7 @@ void XXXNeverCalled()
|
|||
nsIThread::GetCurrent(NULL);
|
||||
nsDeque(NULL);
|
||||
NS_NewObserver(NULL, NULL);
|
||||
nsTraceRefcnt::DumpAllStatistics();
|
||||
nsTraceRefcnt::DumpStatistics();
|
||||
nsXPIDLCString::Copy(NULL);
|
||||
NS_NewEmptyEnumerator(NULL);
|
||||
nsArrayEnumerator(NULL);
|
||||
|
|
|
@ -485,7 +485,7 @@ nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
|
|||
|
||||
NS_PurgeAtomTable();
|
||||
|
||||
nsTraceRefcnt::DumpAllStatistics();
|
||||
nsTraceRefcnt::DumpStatistics();
|
||||
nsTraceRefcnt::ResetStatistics();
|
||||
|
||||
#ifdef GC_LEAK_DETECTOR
|
||||
|
|
Загрузка…
Ссылка в новой задаче