2016-12-08 3 views
1

Я запускаю простой сборщик идентификаторов объектов на большом git repo (в данном случае linux-2.6), готовясь к хранению идентификаторов в базе данных sqlite.Почему я вижу дубликаты идентификаторов объектов при использовании git_odb_foreach?

Псевдо-код:

// Table holding the SHA1 of each object in the database, ensure ids are unique 
CREATE TABLE objs(key INTEGER PRIMARY KEY, id BLOB UNIQUE); 

// For each id, insert into objs table, rc can tell us if we violate uniqueness constraint 
int callback(const git_oid *oid, void *payload) { 
    // note that 'oid' in the following string is really the id value in real code 
    int rc = sqlite3_exec("INSERT INTO objs(id) VALUES(oid);"); 
    if (rc == SQLITE_CONSTRAINT) { 
      // code to print type and oid 
    } 
} 

int main() { 
    // sqlite and git initialization 
    git_odb_foreach(...callback...); 
    // cleanup 
    return 0; 
} 

Out из ~ 4 миллионов объектов, есть ~ 70000 неуникальных объектов я в конечном итоге встретив по пути. Интересно, что при запуске 'git rev-list -objects -all | wc -l ', этот счетчик соответствует количеству уникальных объектов из кода foreach.

Может кто-нибудь объяснить, почему функция git_odb_foreach создаст эти уникальные идентификаторы?

ответ

1

Объекты Git могут храниться в более чем одном пакете, в дополнение к существующему как свободный объект. Это просто что-то, что может произойти, и что git-реализация должна иметь дело.

В то время как git/libgit2/вообще будет проверять, существует ли объект перед его созданием, нет способа сделать это определение, когда вы говорите с пультом дистанционного управления.

Если удаленный объект имеет одни и те же объекты в истории, которые вы загружаете, но невозможно обнаружить это через согласование (которое только обменивает несколько идентификаторов фиксации), тогда пульт может отправить вам объекты, которые у вас уже есть. Эти объекты входят в пакетный файл, и нет никакой логики, чтобы избавиться от дубликатов вне сбора мусора, что может занять довольно много времени.

Наличие одного и того же объекта в разных packfiles может даже повысить производительность, так как вы сможете использовать объекты, которые ближе друг к другу и делиться цепочками дельта, а не открывать другой пакетный файл.

Все git_odb_foreach действительно проходит через каждый сервер и вызывает обратный вызов с тем, что он находит. Он не пытается дедуплицировать, поскольку не может знать, что вы хотите сделать. Поэтому, если объекты существуют как свободные, так и упакованные, или в нескольких packfiles, то это то, что он вернет.

Обратите внимание, что ваша команда git rev-list --objects --all | wc -l делает что-то очень отличное от звонка git_odb_foreach. Команда запрашивает все объекты , достижимые по ссылкам, тогда как вызов функции получает все существующие объекты и во многих случаях (возможно, большинство) эти числа не совпадают. Например. если вы когда-нибудь сделаете git add, в объекте db появится blob, который не будет доступен из любой ссылки.

 Смежные вопросы

  • Нет связанных вопросов^_^