Bug 1507750 - Compare the flexbox state for any changes before updating on reflows...
[gecko.git] / toolkit / xre / AutoSQLiteLifetime.cpp
blob041f470c28218b80bee5a00c0f7b620bba0d86f0
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsDebug.h"
7 #include "AutoSQLiteLifetime.h"
8 #include "sqlite3.h"
10 #ifdef MOZ_STORAGE_MEMORY
11 # include "mozmemory.h"
12 # ifdef MOZ_DMD
13 # include "DMD.h"
14 # endif
16 namespace {
18 // By default, SQLite tracks the size of all its heap blocks by adding an extra
19 // 8 bytes at the start of the block to hold the size. Unfortunately, this
20 // causes a lot of 2^N-sized allocations to be rounded up by jemalloc
21 // allocator, wasting memory. For example, a request for 1024 bytes has 8
22 // bytes added, becoming a request for 1032 bytes, and jemalloc rounds this up
23 // to 2048 bytes, wasting 1012 bytes. (See bug 676189 for more details.)
25 // So we register jemalloc as the malloc implementation, which avoids this
26 // 8-byte overhead, and thus a lot of waste. This requires us to provide a
27 // function, sqliteMemRoundup(), which computes the actual size that will be
28 // allocated for a given request. SQLite uses this function before all
29 // allocations, and may be able to use any excess bytes caused by the rounding.
31 // Note: the wrappers for malloc, realloc and moz_malloc_usable_size are
32 // necessary because the sqlite_mem_methods type signatures differ slightly
33 // from the standard ones -- they use int instead of size_t. But we don't need
34 // a wrapper for free.
36 #ifdef MOZ_DMD
38 // sqlite does its own memory accounting, and we use its numbers in our memory
39 // reporters. But we don't want sqlite's heap blocks to show up in DMD's
40 // output as unreported, so we mark them as reported when they're allocated and
41 // mark them as unreported when they are freed.
43 // In other words, we are marking all sqlite heap blocks as reported even
44 // though we're not reporting them ourselves. Instead we're trusting that
45 // sqlite is fully and correctly accounting for all of its heap blocks via its
46 // own memory accounting. Well, we don't have to trust it entirely, because
47 // it's easy to keep track (while doing this DMD-specific marking) of exactly
48 // how much memory SQLite is using. And we can compare that against what
49 // SQLite reports it is using.
51 MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(SqliteMallocSizeOfOnAlloc)
52 MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(SqliteMallocSizeOfOnFree)
54 #endif
56 static void *sqliteMemMalloc(int n)
58 void* p = ::malloc(n);
59 #ifdef MOZ_DMD
60 gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(p);
61 #endif
62 return p;
65 static void sqliteMemFree(void *p)
67 #ifdef MOZ_DMD
68 gSqliteMemoryUsed -= SqliteMallocSizeOfOnFree(p);
69 #endif
70 ::free(p);
73 static void *sqliteMemRealloc(void *p, int n)
75 #ifdef MOZ_DMD
76 gSqliteMemoryUsed -= SqliteMallocSizeOfOnFree(p);
77 void *pnew = ::realloc(p, n);
78 if (pnew) {
79 gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(pnew);
80 } else {
81 // realloc failed; undo the SqliteMallocSizeOfOnFree from above
82 gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(p);
84 return pnew;
85 #else
86 return ::realloc(p, n);
87 #endif
90 static int sqliteMemSize(void *p)
92 return ::moz_malloc_usable_size(p);
95 static int sqliteMemRoundup(int n)
97 n = malloc_good_size(n);
99 // jemalloc can return blocks of size 2 and 4, but SQLite requires that all
100 // allocations be 8-aligned. So we round up sub-8 requests to 8. This
101 // wastes a small amount of memory but is obviously safe.
102 return n <= 8 ? 8 : n;
105 static int sqliteMemInit(void *p)
107 return 0;
110 static void sqliteMemShutdown(void *p)
114 const sqlite3_mem_methods memMethods = {
115 &sqliteMemMalloc,
116 &sqliteMemFree,
117 &sqliteMemRealloc,
118 &sqliteMemSize,
119 &sqliteMemRoundup,
120 &sqliteMemInit,
121 &sqliteMemShutdown,
122 nullptr
125 } // namespace
127 #endif // MOZ_STORAGE_MEMORY
129 namespace mozilla {
131 AutoSQLiteLifetime::AutoSQLiteLifetime()
133 if (++AutoSQLiteLifetime::sSingletonEnforcer != 1) {
134 MOZ_CRASH("multiple instances of AutoSQLiteLifetime constructed!");
137 #ifdef MOZ_STORAGE_MEMORY
138 sResult = ::sqlite3_config(SQLITE_CONFIG_MALLOC, &memMethods);
139 #else
140 sResult = SQLITE_OK;
141 #endif
143 if (sResult == SQLITE_OK) {
144 // TODO (bug 1191405): do not preallocate the connections caches until we
145 // have figured the impact on our consumers and memory.
146 sqlite3_config(SQLITE_CONFIG_PAGECACHE, NULL, 0, 0);
148 // Explicitly initialize sqlite3. Although this is implicitly called by
149 // various sqlite3 functions (and the sqlite3_open calls in our case),
150 // the documentation suggests calling this directly. So we do.
151 sResult = ::sqlite3_initialize();
155 AutoSQLiteLifetime::~AutoSQLiteLifetime()
157 // Shutdown the sqlite3 API. Warn if shutdown did not turn out okay, but
158 // there is nothing actionable we can do in that case.
159 sResult = ::sqlite3_shutdown();
160 NS_WARNING_ASSERTION(sResult == SQLITE_OK,
161 "sqlite3 did not shutdown cleanly.");
164 int AutoSQLiteLifetime::sSingletonEnforcer = 0;
165 int AutoSQLiteLifetime::sResult = SQLITE_MISUSE;
167 } // namespace mozilla