summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 5ba8106)
raw | patch | inline | side by side (parent: 5ba8106)
author | Jonas Fonseca <fonseca@diku.dk> | |
Tue, 17 Feb 2009 00:51:26 +0000 (01:51 +0100) | ||
committer | Jonas Fonseca <fonseca@diku.dk> | |
Tue, 17 Feb 2009 11:55:19 +0000 (12:55 +0100) |
Numbers from an old linux kernel repository with 2740 unique authors
shows that it takes a little longer time to start up but the gain is
quite good. Furthermore, it lifts the name length restriction.
18191 fonseca 20 0 19712 17m 872 S 3 0.8 0:01.34 tig
18180 fonseca 20 0 23224 20m 868 S 0 1.0 0:01.26 tig-0.14.1
shows that it takes a little longer time to start up but the gain is
quite good. Furthermore, it lifts the name length restriction.
18191 fonseca 20 0 19712 17m 872 S 3 0.8 0:01.34 tig
18180 fonseca 20 0 23224 20m 868 S 0 1.0 0:01.26 tig-0.14.1
tig.c | patch | blob | history |
index 180661a4fcfbc94067a795898df1a6fc6a6e0330..20f7d5498cf32ef16d0aba335985e6c8456a96f1 100644 (file)
--- a/tig.c
+++ b/tig.c
* View backend utilities
*/
+/* Small author cache to reduce memory consumption. It uses binary
+ * search to lookup or find place to position new entries. No entries
+ * are ever freed. */
+static const char *
+get_author(const char *name)
+{
+ static const char **authors;
+ static size_t authors_alloc;
+ static size_t authors_size;
+ const char **tmp;
+ int from = 0, to = authors_size - 1;
+
+ while (from <= to) {
+ size_t pos = (to + from) / 2;
+ int cmp = strcmp(name, authors[pos]);
+
+ if (!cmp)
+ return authors[pos];
+
+ if (cmp < 0)
+ to = pos - 1;
+ else
+ from = pos + 1;
+ }
+
+ tmp = realloc_items(authors, &authors_alloc, authors_size + 1, sizeof(*authors));
+ if (!tmp)
+ return NULL;
+ name = strdup(name);
+ if (!name)
+ return NULL;
+
+ authors = tmp;
+ memmove(authors + from + 1, authors + from, (authors_size - from) * sizeof(*authors));
+ authors[from] = name;
+ authors_size++;
+
+ return name;
+}
+
static void
parse_timezone(time_t *time, const char *zone)
{
* author <email@address.tld> 1138474660 +0100
*/
static void
-parse_author_line(char *ident, char *author, size_t authorsize, struct tm *tm)
+parse_author_line(char *ident, const char **author, struct tm *tm)
{
char *nameend = strchr(ident, '<');
char *emailend = strchr(ident, '>');
@@ -3363,7 +3403,7 @@ parse_author_line(char *ident, char *author, size_t authorsize, struct tm *tm)
ident = "Unknown";
}
- string_ncopy_do(author, authorsize, ident, strlen(ident));
+ *author = get_author(ident);
/* Parse epoch and timezone */
if (emailend && emailend[1] == ' ') {
char id[SIZEOF_REV];
mode_t mode;
struct tm time; /* Date from the author ident. */
- char author[75]; /* Author of the commit. */
+ const char *author; /* Author of the commit. */
char name[1];
};
static bool
tree_read_date(struct view *view, char *text, bool *read_date)
{
- static char author_name[SIZEOF_STR];
+ static const char *author_name;
static struct tm author_time;
if (!text && *read_date) {
} else if (*text == 'a' && get_line_type(text) == LINE_AUTHOR) {
parse_author_line(text + STRING_SIZE("author "),
- author_name, sizeof(author_name), &author_time);
+ &author_name, &author_time);
} else if (*text == ':') {
char *pos;
struct line *line = &view->line[i];
struct tree_entry *entry = line->data;
- annotated += !!*entry->author;
- if (*entry->author || strcmp(entry->name, text))
+ annotated += !!entry->author;
+ if (entry->author || strcmp(entry->name, text))
continue;
- string_copy(entry->author, author_name);
+ entry->author = author_name;
memcpy(&entry->time, &author_time, sizeof(entry->time));
line->dirty = 1;
break;
if (opt_author && draw_author(view, entry->author))
return TRUE;
- if (opt_date && draw_date(view, *entry->author ? &entry->time : NULL))
+ if (opt_date && draw_date(view, entry->author ? &entry->time : NULL))
return TRUE;
}
if (draw_text(view, line->type, entry->name, TRUE))
struct blame_commit {
char id[SIZEOF_REV]; /* SHA1 ID. */
char title[128]; /* First line of the commit message. */
- char author[75]; /* Author of the commit. */
+ const char *author; /* Author of the commit. */
struct tm time; /* Date from the author ident. */
char filename[128]; /* Name of file. */
bool has_previous; /* Was a "previous" line detected. */
view->lines ? blamed * 100 / view->lines : 0);
} else if (match_blame_header("author ", &line)) {
- string_ncopy(commit->author, line, strlen(line));
+ commit->author = get_author(line);
} else if (match_blame_header("author-time ", &line)) {
author_time = (time_t) atol(line);
struct commit {
char id[SIZEOF_REV]; /* SHA1 ID. */
char title[128]; /* First line of the commit message. */
- char author[75]; /* Author of the commit. */
+ const char *author; /* Author of the commit. */
struct tm time; /* Date from the author ident. */
struct ref **refs; /* Repository references. */
chtype graph[SIZEOF_REVGRAPH]; /* Ancestry chain graphics. */
{
struct commit *commit = line->data;
- if (!*commit->author)
+ if (!commit->author)
return FALSE;
if (opt_date && draw_date(view, &commit->time))
if (view->lines > 0) {
commit = view->line[view->lines - 1].data;
view->line[view->lines - 1].dirty = 1;
- if (!*commit->author) {
+ if (!commit->author) {
view->lines--;
free(commit);
graph->commit = NULL;
case LINE_AUTHOR:
parse_author_line(line + STRING_SIZE("author "),
- commit->author, sizeof(commit->author),
- &commit->time);
+ &commit->author, &commit->time);
update_rev_graph(view, graph);
graph = graph->next;
break;
regmatch_t pmatch;
for (state = S_TITLE; state < S_END; state++) {
- char *text;
+ const char *text;
switch (state) {
case S_TITLE: text = commit->title; break;