22
#include "commit.h"
23
#include "packfile.h"
24
#include "object-store.h"
25
+#include "pack.h"
26
+#include "pack-objects.h"
27
+#include "blob.h"
28
+#include "tree.h"
29
30
#define FAILED_RUN "failed to run %s"
31
46
static const char *prune_expire = "2.weeks.ago";
47
static const char *prune_worktrees_expire = "3.months.ago";
48
static unsigned long big_pack_threshold;
49
+static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;
50
51
static struct argv_array pack_refs_cmd = ARGV_ARRAY_INIT;
52
static struct argv_array reflog = ARGV_ARRAY_INIT;
135
git_config_get_expiry("gc.logexpiry", &gc_log_expire);
136
137
git_config_get_ulong("gc.bigpackthreshold", &big_pack_threshold);
138
+ git_config_get_ulong("pack.deltacachesize", &max_delta_cache_size);
139
140
git_config(git_default_config, NULL);
141
}
175
return needed;
176
}
177
172
-static void find_base_packs(struct string_list *packs, unsigned long limit)
178
+static struct packed_git *find_base_packs(struct string_list *packs,
179
+ unsigned long limit)
180
{
181
struct packed_git *p, *base = NULL;
182
193
194
if (base)
195
string_list_append(packs, base->pack_name);
196
+
197
+ return base;
198
}
199
200
static int too_many_packs(void)
219
return gc_auto_pack_limit < cnt;
220
}
221
222
+static uint64_t total_ram(void)
223
+{
224
+#if defined(HAVE_SYSINFO)
225
+ struct sysinfo si;
226
+
227
+ if (!sysinfo(&si))
228
+ return si.totalram;
229
+#elif defined(HAVE_BSD_SYSCTL) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM))
230
+ int64_t physical_memory;
231
+ int mib[2];
232
+ size_t length;
233
+
234
+ mib[0] = CTL_HW;
235
+# if defined(HW_MEMSIZE)
236
+ mib[1] = HW_MEMSIZE;
237
+# else
238
+ mib[1] = HW_PHYSMEM;
239
+# endif
240
+ length = sizeof(int64_t);
241
+ if (!sysctl(mib, 2, &physical_memory, &length, NULL, 0))
242
+ return physical_memory;
243
+#elif defined(GIT_WINDOWS_NATIVE)
244
+ MEMORYSTATUSEX memInfo;
245
+
246
+ memInfo.dwLength = sizeof(MEMORYSTATUSEX);
247
+ if (GlobalMemoryStatusEx(&memInfo))
248
+ return memInfo.ullTotalPhys;
249
+#endif
250
+ return 0;
251
+}
252
+
253
+static uint64_t estimate_repack_memory(struct packed_git *pack)
254
+{
255
+ unsigned long nr_objects = approximate_object_count();
256
+ size_t os_cache, heap;
257
+
258
+ if (!pack || !nr_objects)
259
+ return 0;
260
+
261
+ /*
262
+ * First we have to scan through at least one pack.
263
+ * Assume enough room in OS file cache to keep the entire pack
264
+ * or we may accidentally evict data of other processes from
265
+ * the cache.
266
+ */
267
+ os_cache = pack->pack_size + pack->index_size;
268
+ /* then pack-objects needs lots more for book keeping */
269
+ heap = sizeof(struct object_entry) * nr_objects;
270
+ /*
271
+ * internal rev-list --all --objects takes up some memory too,
272
+ * let's say half of it is for blobs
273
+ */
274
+ heap += sizeof(struct blob) * nr_objects / 2;
275
+ /*
276
+ * and the other half is for trees (commits and tags are
277
+ * usually insignificant)
278
+ */
279
+ heap += sizeof(struct tree) * nr_objects / 2;
280
+ /* and then obj_hash[], underestimated in fact */
281
+ heap += sizeof(struct object *) * nr_objects;
282
+ /* revindex is used also */
283
+ heap += sizeof(struct revindex_entry) * nr_objects;
284
+ /*
285
+ * read_sha1_file() (either at delta calculation phase, or
286
+ * writing phase) also fills up the delta base cache
287
+ */
288
+ heap += delta_base_cache_limit;
289
+ /* and of course pack-objects has its own delta cache */
290
+ heap += max_delta_cache_size;
291
+
292
+ return os_cache + heap;
293
+}
294
+
295
static int keep_one_pack(struct string_list_item *item, void *data)
296
{
297
argv_array_pushf(&repack, "--keep-pack=%s", basename(item->string));
342
string_list_clear(&keep_pack, 0);
343
find_base_packs(&keep_pack, 0);
344
}
345
+ } else {
346
+ struct packed_git *p = find_base_packs(&keep_pack, 0);
347
+ uint64_t mem_have, mem_want;
348
+
349
+ mem_have = total_ram();
350
+ mem_want = estimate_repack_memory(p);
351
+
352
+ /*
353
+ * Only allow 1/2 of memory for pack-objects, leave
354
+ * the rest for the OS and other processes in the
355
+ * system.
356
+ */
357
+ if (!mem_have || mem_want < mem_have / 2)
358
+ string_list_clear(&keep_pack, 0);
359
}
360
361
add_repack_all_option(&keep_pack);