Rules: mmap() rules file instead of using getc() Good for a small performance win on my system. Signed-off-by: Daniel Stone <daniel@fooishbar.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
diff --git a/src/xkbcomp/rules.c b/src/xkbcomp/rules.c
index 008f9a6..622d42c 100644
--- a/src/xkbcomp/rules.c
+++ b/src/xkbcomp/rules.c
@@ -26,28 +26,33 @@
#include <stdio.h>
#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include "rules.h"
#include "path.h"
-static bool
-input_line_get(struct xkb_context *ctx, FILE *file, darray_char *line)
+static const char *
+input_line_get(struct xkb_context *ctx, const char *buf, const char *end,
+ darray_char *line)
{
int ch;
- bool end_of_file = false;
bool space_pending;
bool slash_pending;
bool in_comment;
- while (!end_of_file && darray_empty(*line)) {
+ while (buf < end && darray_empty(*line)) {
space_pending = slash_pending = in_comment = false;
- while ((ch = getc(file)) != '\n' && ch != EOF) {
+ while (buf < end && (ch = *buf++) != '\n') {
if (ch == '\\') {
- ch = getc(file);
-
- if (ch == EOF)
+ buf++;
+ if (buf >= end)
break;
+ ch = *buf;
if (ch == '\n') {
in_comment = false;
@@ -81,16 +86,16 @@ input_line_get(struct xkb_context *ctx, FILE *file, darray_char *line)
}
if (isspace(ch)) {
- while (isspace(ch) && ch != '\n' && ch != EOF)
- ch = getc(file);
+ while (buf < end && isspace(ch) && ch != '\n')
+ ch = *buf++;
- if (ch == EOF)
+ if (buf >= end)
break;
if (ch != '\n' && !darray_empty(*line))
space_pending = true;
- ungetc(ch, file);
+ buf--;
}
else {
if (space_pending) {
@@ -111,16 +116,13 @@ input_line_get(struct xkb_context *ctx, FILE *file, darray_char *line)
darray_append(*line, ch);
}
}
-
- if (ch == EOF)
- end_of_file = true;
}
- if (darray_empty(*line) && end_of_file)
- return false;
+ if (darray_empty(*line) && buf >= end)
+ return NULL;
darray_append(*line, '\0');
- return true;
+ return buf;
}
/***====================================================================***/
@@ -986,6 +988,22 @@ load_rules(struct xkb_context *ctx, FILE *file)
struct rule trule;
struct group tgroup;
struct rules *rules;
+ struct stat stat_buf;
+ const char *buf, *end;
+ char *orig;
+ int fd = fileno(file);
+
+ if (fstat(fd, &stat_buf) != 0) {
+ log_err(ctx, "couldn't stat rules file\n");
+ return NULL;
+ }
+
+ orig = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (!orig) {
+ log_err(ctx, "couldn't mmap rules file (%zu bytes)\n",
+ stat_buf.st_size);
+ return NULL;
+ }
rules = calloc(1, sizeof(*rules));
if (!rules)
@@ -998,7 +1016,9 @@ load_rules(struct xkb_context *ctx, FILE *file)
darray_init(line);
darray_growalloc(line, 128);
- while (input_line_get(ctx, file, &line)) {
+ buf = orig;
+ end = orig + stat_buf.st_size;
+ while ((buf = input_line_get(ctx, buf, end, &line))) {
if (match_line(ctx, &line, &mapping, &trule, &tgroup)) {
if (tgroup.number) {
darray_append(rules->groups, tgroup);
@@ -1013,6 +1033,8 @@ load_rules(struct xkb_context *ctx, FILE *file)
darray_resize(line, 0);
}
+ munmap(orig, stat_buf.st_size);
+
darray_free(line);
return rules;
}
@@ -1051,11 +1073,11 @@ struct xkb_component_names *
xkb_components_from_rules(struct xkb_context *ctx,
const struct xkb_rule_names *rmlvo)
{
+ struct rules *rules;
+ struct xkb_component_names *kccgst = NULL;
FILE *file;
char *path;
char **include;
- struct rules *rules;
- struct xkb_component_names *kccgst = NULL;
file = XkbFindFileInPath(ctx, rmlvo->rules, FILE_TYPE_RULES, &path);
if (!file) {