Skip to content

Commit 434010a

Browse files
author
Yorick Peterse
committed
Added Rugged::Walker#count
This method counts the amount of objects a Walker would iterate over without allocating any Ruby objects. If one were to use the default "count" method (as added by Enumerable) every call would end up allocating Rugged::Commit objects for every commit (as "count" simply calls "each"). Timing wise the differences aren't _that_ big. For example, take the following benchmark: require 'rugged' require 'benchmark/ips' rugged = Rugged::Repository.new('path/to/gitlab-ce.git') from = rugged.rev_parse_oid('5-4-stable') to = rugged.rev_parse_oid('master') Benchmark.ips do |bench| bench.report 'each' do walker = Rugged::Walker.new(rugged) count = 0 walker.push(to) walker.hide(from) walker.each { count += 1 } end bench.report 'each_oid' do walker = Rugged::Walker.new(rugged) count = 0 walker.push(to) walker.hide(from) walker.each_oid { count += 1 } end bench.report 'count' do walker = Rugged::Walker.new(rugged) walker.push(to) walker.hide(from) walker.count end bench.compare! end Here 'path/to/gitlab-ce.git' refers to a local clone of GitLab Community Edition (https://gitlab.com/gitlab-org/gitlab-ce). This benchmark spits out the following output: Warming up -------------------------------------- each 1.000 i/100ms each_oid 1.000 i/100ms count 1.000 i/100ms Calculating ------------------------------------- each 6.753 (± 0.0%) i/s - 34.000 each_oid 7.374 (± 0.0%) i/s - 37.000 count 7.557 (± 0.0%) i/s - 38.000 Comparison: count: 7.6 i/s each_oid: 7.4 i/s - 1.02x slower each: 6.8 i/s - 1.12x slower In other words, while the amount of object allocations can be greatly reduced the actual runtime is not _that_ much better. Regardless, not having to allocate as many objects as before is still a win.
1 parent 1db069f commit 434010a

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

ext/rugged/rugged_revwalk.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,29 @@ static VALUE rb_git_walker_simplify_first_parent(VALUE self)
190190
return Qnil;
191191
}
192192

193+
/*
194+
* call-seq:
195+
* walker.count -> Fixnum
196+
*
197+
* Returns the amount of objects a walker iterated over.
198+
*/
199+
static VALUE rb_git_walker_count(VALUE self)
200+
{
201+
git_revwalk *walk;
202+
git_oid commit_oid;
203+
int error = 0;
204+
uint64_t count = 0;
205+
206+
Data_Get_Struct(self, git_revwalk, walk);
207+
208+
while (((error = git_revwalk_next(&commit_oid, walk)) == 0) && ++count != UINT64_MAX);
209+
210+
if (error != GIT_ITEROVER)
211+
rugged_exception_check(error);
212+
213+
return ULONG2NUM(count);
214+
}
215+
193216
/*
194217
* call-seq:
195218
* walker.reset -> nil
@@ -492,4 +515,5 @@ void Init_rugged_revwalk(void)
492515
rb_define_method(rb_cRuggedWalker, "reset", rb_git_walker_reset, 0);
493516
rb_define_method(rb_cRuggedWalker, "sorting", rb_git_walker_sorting, 1);
494517
rb_define_method(rb_cRuggedWalker, "simplify_first_parent", rb_git_walker_simplify_first_parent, 0);
518+
rb_define_method(rb_cRuggedWalker, "count", rb_git_walker_count, 0);
495519
}

test/walker_test.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ def test_walk_api
143143
oids = data.sort { |a, b| a.oid <=> b.oid }.map {|a| a.oid[0,5]}.join('.')
144144
assert_equal "4a202.5b5b0.84960.9fd73", oids
145145
end
146+
147+
def test_walk_count
148+
@walker.push("9fd738e8f7967c078dceed8190330fc8648ee56a")
149+
@walker.hide("5b5b025afb0b4c913b4c338a42934a3863bf3644")
150+
assert_equal 2, @walker.count
151+
end
146152
end
147153

148154
# testrepo (the non-bare repo) is the one with non-linear history,

0 commit comments

Comments
 (0)