Commit afe74e99 authored by Kjartan Maraas's avatar Kjartan Maraas Committed by Kjartan Maraas

Add patch for excessive memory consumption when opening new tabs. This

2005-03-14  Kjartan Maraas  <kmaraas@gnome.org>

	* src/Makefile.am:
	* src/interpret.c: (main):
	* src/matcher.c: (_vte_matcher_add), (_vte_matcher_init),
	(_vte_matcher_create), (_vte_matcher_destroy), (_vte_matcher_new),
	(_vte_matcher_free):
	* src/matcher.h:
	* src/vte.c: (vte_terminal_set_emulation), (vte_terminal_init):
	* src/vtetc.c: (_vte_termcap_create), (_vte_termcap_destroy),
	(_vte_termcap_new), (_vte_termcap_free):
	* src/vtetc.h: Add patch for excessive memory consumption when
	opening new tabs. This patch makes struct _vte_matcher and
	struct _vte_termcap shared between terminals and should reduce
	memory consumption with multiple tabs a lot. Patch from Aivars
	Kalvans <kalvans at inbox lv>. From bug #160993.
parent 1613c775
2005-03-14 Kjartan Maraas <kmaraas@gnome.org>
* src/Makefile.am:
* src/interpret.c: (main):
* src/matcher.c: (_vte_matcher_add), (_vte_matcher_init),
(_vte_matcher_create), (_vte_matcher_destroy), (_vte_matcher_new),
(_vte_matcher_free):
* src/matcher.h:
* src/vte.c: (vte_terminal_set_emulation), (vte_terminal_init):
* src/vtetc.c: (_vte_termcap_create), (_vte_termcap_destroy),
(_vte_termcap_new), (_vte_termcap_free):
* src/vtetc.h: Add patch for excessive memory consumption when
opening new tabs. This patch makes struct _vte_matcher and
struct _vte_termcap shared between terminals and should reduce
memory consumption with multiple tabs a lot. Patch from Aivars
Kalvans <kalvans at inbox lv>. From bug #160993.
2005-03-14 Kjartan Maraas <kmaraas@gnome.org>
* src/vte.c: (vte_terminal_scroll_region),
......
......@@ -155,6 +155,8 @@ iso2022_CFLAGS = @CFLAGS@ @GTK_CFLAGS@ -DISO2022_MAIN
iso2022_SOURCES = \
buffer.c \
buffer.h \
caps.c \
caps.h \
debug.c \
debug.h \
iso2022.c \
......@@ -166,13 +168,17 @@ iso2022_SOURCES = \
trie.c \
trie.h \
vteconv.c \
vteconv.h
vteconv.h \
vtetc.c \
vtetc.h
iso2022_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
utf8echo_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DUTF8ECHO_MAIN
utf8echo_SOURCES = \
buffer.c \
buffer.h \
caps.c \
caps.h \
debug.c \
debug.h \
matcher.c \
......@@ -183,7 +189,9 @@ utf8echo_SOURCES = \
trie.h \
utf8echo.c \
vteconv.c \
vteconv.h
vteconv.h \
vtetc.c \
vtetc.h
utf8echo_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
nativeecho_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@ -DNATIVEECHO_MAIN
......@@ -207,6 +215,8 @@ table_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DTABLE_MAIN
table_SOURCES = \
buffer.c \
buffer.h \
caps.c \
caps.h \
debug.c \
debug.h \
matcher.c \
......@@ -216,13 +226,17 @@ table_SOURCES = \
trie.c \
trie.h \
vteconv.c \
vteconv.h
vteconv.h \
vtetc.c \
vtetc.h
table_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
trie_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DTRIE_MAIN
trie_SOURCES = \
buffer.c \
buffer.h \
caps.c \
caps.h \
debug.c \
debug.h \
matcher.c \
......@@ -234,7 +248,7 @@ trie_SOURCES = \
vteconv.c \
vteconv.h \
vtetc.c \
vtetc.h
vtetc.h
trie_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
vtetc_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@ -DTERMCAP_MAIN
......
......@@ -72,7 +72,6 @@ main(int argc, char **argv)
g_type_init();
terminal = argv[1];
matcher = _vte_matcher_new(terminal);
termcap = _vte_termcap_new(g_strdup_printf(DATADIR "/" PACKAGE
"/termcap/%s", terminal));
if (termcap == NULL) {
......@@ -81,29 +80,7 @@ main(int argc, char **argv)
buffer = _vte_buffer_new();
array = g_array_new(TRUE, TRUE, sizeof(gunichar));
for (i = 0;
_vte_terminal_capability_strings[i].capability != NULL;
i++) {
const char *capability;
char *tmp;
capability = _vte_terminal_capability_strings[i].capability;
if (_vte_terminal_capability_strings[i].key) {
continue;
}
tmp = _vte_termcap_find_string(termcap, terminal, capability);
if ((tmp != NULL) && (strlen(tmp) > 0)) {
_vte_matcher_add(matcher, tmp, strlen(tmp), capability,
g_quark_from_static_string(capability));
}
g_free(tmp);
}
for (i = 0; _vte_xterm_capability_strings[i].value != NULL; i++) {
const char *code, *value;
code = _vte_xterm_capability_strings[i].code;
value = _vte_xterm_capability_strings[i].value;
_vte_matcher_add(matcher, code, strlen(code), value,
g_quark_from_static_string(code));
}
matcher = _vte_matcher_new(terminal, termcap);
subst = _vte_iso2022_state_new(NULL, NULL, NULL);
......
......@@ -24,11 +24,13 @@
#include <string.h>
#include <glib-object.h>
#include "debug.h"
#include "caps.h"
#include "matcher.h"
#include "table.h"
#include "trie.h"
struct _vte_matcher {
gboolean initialized;
enum {
_vte_matcher_table,
_vte_matcher_trie
......@@ -37,23 +39,128 @@ struct _vte_matcher {
struct _vte_trie *trie;
};
/* Create an initial matcher. */
struct _vte_matcher *
_vte_matcher_new(const char *emulation_hint)
static GStaticMutex _vte_matcher_mutex = G_STATIC_MUTEX_INIT;
static GCache *_vte_matcher_cache = NULL;
/* Add a string to the matcher. */
static void
_vte_matcher_add(struct _vte_matcher *matcher,
const char *pattern, gssize length,
const char *result, GQuark quark)
{
switch (matcher->type) {
case _vte_matcher_table:
_vte_table_add(matcher->table, pattern, length, result, quark);
break;
case _vte_matcher_trie:
_vte_trie_add(matcher->trie, pattern, length, result, quark);
break;
}
}
/* Loads all sequences into matcher */
static void
_vte_matcher_init(struct _vte_matcher *matcher, char *emulation,
struct _vte_termcap *termcap)
{
const char *code, *value;
gboolean found_cr = FALSE, found_lf = FALSE;
gssize stripped_length;
char *stripped;
char *tmp;
int i;
#ifdef VTE_DEBUG
if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
fprintf(stderr, "_vte_matcher_init()\n");
}
#endif
/* Load the known capability strings from the termcap structure into
* the table for recognition. */
for (i = 0;
_vte_terminal_capability_strings[i].capability != NULL;
i++) {
if (_vte_terminal_capability_strings[i].key) {
continue;
}
code = _vte_terminal_capability_strings[i].capability;
tmp = _vte_termcap_find_string(termcap, emulation, code);
if ((tmp != NULL) && (tmp[0] != '\0')) {
_vte_termcap_strip(tmp, &stripped, &stripped_length);
_vte_matcher_add(matcher, stripped, stripped_length,
code, 0);
if (stripped[0] == '\r') {
found_cr = TRUE;
} else
if (stripped[0] == '\n') {
if ((strcmp(code, "sf") == 0) ||
(strcmp(code, "do") == 0)) {
found_lf = TRUE;
}
}
g_free(stripped);
}
g_free(tmp);
}
/* Add emulator-specific sequences. */
if (strstr(emulation, "xterm") || strstr(emulation, "dtterm")) {
/* Add all of the xterm-specific stuff. */
for (i = 0;
_vte_xterm_capability_strings[i].value != NULL;
i++) {
code = _vte_xterm_capability_strings[i].code;
value = _vte_xterm_capability_strings[i].value;
_vte_termcap_strip(code, &stripped, &stripped_length);
_vte_matcher_add(matcher, stripped, stripped_length,
value, 0);
g_free(stripped);
}
}
/* Always define cr and lf. */
if (!found_cr) {
_vte_matcher_add(matcher, "\r", 1, "cr", 0);
}
if (!found_lf) {
_vte_matcher_add(matcher, "\n", 1, "sf", 0);
}
#ifdef VTE_DEBUG
if (_vte_debug_on(VTE_DEBUG_MISC)) {
fprintf(stderr, "Trie contents:\n");
_vte_matcher_print(matcher);
fprintf(stderr, "\n");
}
#endif
}
/* Allocates new matcher structure. */
static gpointer
_vte_matcher_create(gpointer key)
{
char *emulation = key;
struct _vte_matcher *ret = NULL;
#ifdef VTE_DEBUG
if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
fprintf(stderr, "_vte_matcher_create()\n");
}
#endif
ret = g_malloc(sizeof(struct _vte_matcher));
ret->initialized = FALSE;
ret->type = _vte_matcher_trie;
ret->table = NULL;
ret->trie = NULL;
if (emulation_hint != NULL) {
if (strcmp(emulation_hint, "xterm") == 0) {
ret->type = _vte_matcher_table;
} else
if (strcmp(emulation_hint, "dtterm") == 0) {
ret->type = _vte_matcher_table;
}
if (strcmp(emulation, "xterm") == 0) {
ret->type = _vte_matcher_table;
} else
if (strcmp(emulation, "dtterm") == 0) {
ret->type = _vte_matcher_table;
}
switch (ret->type) {
case _vte_matcher_table:
ret->table = _vte_table_new();
......@@ -62,13 +169,21 @@ _vte_matcher_new(const char *emulation_hint)
ret->trie = _vte_trie_new();
break;
}
return ret;
}
/* Free a matcher. */
void
_vte_matcher_free(struct _vte_matcher *matcher)
/* Noone uses this matcher, free it. */
static void
_vte_matcher_destroy(gpointer value)
{
struct _vte_matcher *matcher = value;
#ifdef VTE_DEBUG
if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
fprintf(stderr, "_vte_matcher_destroy()\n");
}
#endif
if (matcher->table != NULL) {
_vte_table_free(matcher->table);
}
......@@ -78,20 +193,42 @@ _vte_matcher_free(struct _vte_matcher *matcher)
g_free(matcher);
}
/* Add a string to the matcher. */
void
_vte_matcher_add(struct _vte_matcher *matcher,
const char *pattern, gssize length,
const char *result, GQuark quark)
/* Create and init matcher. */
struct _vte_matcher *
_vte_matcher_new(char *emulation, struct _vte_termcap *termcap)
{
switch (matcher->type) {
case _vte_matcher_table:
_vte_table_add(matcher->table, pattern, length, result, quark);
break;
case _vte_matcher_trie:
_vte_trie_add(matcher->trie, pattern, length, result, quark);
break;
struct _vte_matcher *ret = NULL;
g_static_mutex_lock(&_vte_matcher_mutex);
if (emulation == NULL) {
emulation = "";
}
if (_vte_matcher_cache == NULL) {
_vte_matcher_cache = g_cache_new(_vte_matcher_create,
_vte_matcher_destroy, g_strdup, g_free,
g_str_hash, g_direct_hash, g_str_equal);
}
ret = g_cache_insert(_vte_matcher_cache, emulation);
if (!ret->initialized) {
_vte_matcher_init(ret, emulation, termcap);
ret->initialized = TRUE;
}
g_static_mutex_unlock(&_vte_matcher_mutex);
return ret;
}
/* Free a matcher. */
void
_vte_matcher_free(struct _vte_matcher *matcher)
{
g_assert(_vte_matcher_cache != NULL);
g_static_mutex_lock(&_vte_matcher_mutex);
g_cache_remove(_vte_matcher_cache, matcher);
g_static_mutex_unlock(&_vte_matcher_mutex);
}
/* Check if a string matches a sequence the matcher knows about. */
......
......@@ -24,22 +24,19 @@
#ident "$Id$"
#include <glib-object.h>
#include "vtetc.h"
G_BEGIN_DECLS
struct _vte_matcher;
/* Create an initial matcher. */
struct _vte_matcher *_vte_matcher_new(const char *emulation_hint);
/* Create and init matcher. */
struct _vte_matcher *_vte_matcher_new(char *emulation,
struct _vte_termcap *termcap);
/* Free a matcher. */
void _vte_matcher_free(struct _vte_matcher *matcher);
/* Add a string to the matcher. */
void _vte_matcher_add(struct _vte_matcher *matcher,
const char *pattern, gssize length,
const char *result, GQuark quark);
/* Check if a string matches a sequence the matcher knows about. */
const char *_vte_matcher_match(struct _vte_matcher *matcher,
const gunichar *pattern, gssize length,
......
......@@ -11003,13 +11003,9 @@ vte_terminal_set_scroll_adjustment(VteTerminal *terminal,
void
vte_terminal_set_emulation(VteTerminal *terminal, const char *emulation)
{
const char *code, *value;
gboolean found_cr = FALSE, found_lf = FALSE;
char *stripped;
gssize stripped_length;
const char *code;
int columns, rows;
GQuark quark;
char *tmp;
int i;
/* Set the emulation type, for reference. */
......@@ -11030,7 +11026,7 @@ vte_terminal_set_emulation(VteTerminal *terminal, const char *emulation)
if (terminal->pvt->matcher != NULL) {
_vte_matcher_free(terminal->pvt->matcher);
}
terminal->pvt->matcher = _vte_matcher_new(emulation);
terminal->pvt->matcher = _vte_matcher_new(emulation, terminal->pvt->termcap);
/* Create a tree to hold the handlers. */
if (terminal->pvt->sequences) {
......@@ -11046,69 +11042,6 @@ vte_terminal_set_emulation(VteTerminal *terminal, const char *emulation)
}
}
/* Load the known capability strings from the termcap structure into
* the table for recognition. */
for (i = 0;
_vte_terminal_capability_strings[i].capability != NULL;
i++) {
if (_vte_terminal_capability_strings[i].key) {
continue;
}
code = _vte_terminal_capability_strings[i].capability;
tmp = _vte_termcap_find_string(terminal->pvt->termcap,
terminal->pvt->emulation,
code);
if ((tmp != NULL) && (tmp[0] != '\0')) {
_vte_termcap_strip(tmp, &stripped, &stripped_length);
_vte_matcher_add(terminal->pvt->matcher,
stripped, stripped_length,
code, 0);
if (stripped[0] == '\r') {
found_cr = TRUE;
} else
if (stripped[0] == '\n') {
if ((strcmp(code, "sf") == 0) ||
(strcmp(code, "do") == 0)) {
found_lf = TRUE;
}
}
g_free(stripped);
}
g_free(tmp);
}
/* Add emulator-specific sequences. */
if (strstr(emulation, "xterm") || strstr(emulation, "dtterm")) {
/* Add all of the xterm-specific stuff. */
for (i = 0;
_vte_xterm_capability_strings[i].value != NULL;
i++) {
code = _vte_xterm_capability_strings[i].code;
value = _vte_xterm_capability_strings[i].value;
_vte_termcap_strip(code, &stripped, &stripped_length);
_vte_matcher_add(terminal->pvt->matcher,
stripped, stripped_length,
value, 0);
g_free(stripped);
}
}
/* Always define cr and lf. */
if (!found_cr) {
_vte_matcher_add(terminal->pvt->matcher, "\r", 1, "cr", 0);
}
if (!found_lf) {
_vte_matcher_add(terminal->pvt->matcher, "\n", 1, "sf", 0);
}
#ifdef VTE_DEBUG
if (_vte_debug_on(VTE_DEBUG_MISC)) {
fprintf(stderr, "Trie contents:\n");
_vte_matcher_print(terminal->pvt->matcher);
fprintf(stderr, "\n");
}
#endif
/* Read emulation flags. */
terminal->pvt->flags.am = _vte_termcap_find_boolean(terminal->pvt->termcap,
terminal->pvt->emulation,
......@@ -11397,7 +11330,6 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
/* Setting the terminal type and size requires the PTY master to
* be set up properly first. */
pvt->pty_master = -1;
vte_terminal_set_termcap(terminal, NULL, FALSE);
vte_terminal_set_emulation(terminal, NULL);
vte_terminal_set_size(terminal,
pvt->default_column_count,
......
......@@ -50,6 +50,9 @@ struct _vte_termcap {
GTree *nametree;
};
static GStaticMutex _vte_termcap_mutex = G_STATIC_MUTEX_INIT;
static GCache *_vte_termcap_cache = NULL;
static char *
nextline(FILE *fp, gssize *outlen)
{
......@@ -334,12 +337,20 @@ _vte_direct_compare(gconstpointer a, gconstpointer b)
return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
}
TERMCAP_MAYBE_STATIC struct _vte_termcap *
_vte_termcap_new(const char *filename)
/* Allocates and initializes new termcap instance. */
static gpointer
_vte_termcap_create(gpointer key)
{
const char *filename = key;
struct _vte_termcap *ret = NULL;
FILE *fp;
char *s, *stripped, *comment = NULL;
struct _vte_termcap *ret = NULL;
#ifdef VTE_DEBUG
if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
fprintf(stderr, "_vte_termcap_create()\n");
}
#endif
fp = fopen(filename, "r");
if (fp != NULL) {
while ((s = nextline_with_continuation(fp)) != NULL) {
......@@ -392,18 +403,19 @@ _vte_termcap_new(const char *filename)
return ret;
}
/**
* _vte_termcap_free:
* @termcap: the structure to be freed
*
* Frees the indicated structure.
*
*/
TERMCAP_MAYBE_STATIC void
_vte_termcap_free(struct _vte_termcap *termcap)
/* Noone uses termcap, destroy it. */
static void
_vte_termcap_destroy(gpointer key)
{
struct _vte_termcap *termcap = key;
struct _vte_termcap_entry *entry, *nextentry;
struct _vte_termcap_alias *alias, *nextalias;
#ifdef VTE_DEBUG
if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
fprintf(stderr, "_vte_termcap_destroy()\n");
}
#endif
for (entry = termcap->entries; entry != NULL; entry = nextentry) {
nextentry = entry->next;
g_free(entry->comment);
......@@ -425,6 +437,39 @@ _vte_termcap_free(struct _vte_termcap *termcap)
g_free(termcap);
}
TERMCAP_MAYBE_STATIC struct _vte_termcap *
_vte_termcap_new(char *filename)
{
struct _vte_termcap *ret = NULL;
g_static_mutex_lock(&_vte_termcap_mutex);
if (_vte_termcap_cache == NULL) {
_vte_termcap_cache = g_cache_new(_vte_termcap_create,
_vte_termcap_destroy, g_strdup, g_free,
g_str_hash, g_direct_hash, g_str_equal);
}
ret = g_cache_insert(_vte_termcap_cache, filename);
g_static_mutex_unlock(&_vte_termcap_mutex);
return ret;
}
/**
* _vte_termcap_free:
* @termcap: the structure to be freed
*
* Frees the indicated structure.
*
*/
TERMCAP_MAYBE_STATIC void
_vte_termcap_free(struct _vte_termcap *termcap)
{
g_assert(_vte_termcap_cache != NULL);
g_static_mutex_lock(&_vte_termcap_mutex);
g_cache_remove(_vte_termcap_cache, termcap);
g_static_mutex_unlock(&_vte_termcap_mutex);
}
static const char *
_vte_termcap_find_l(struct _vte_termcap *termcap, const char *tname, gssize len,
const char *cap)
......
......@@ -30,7 +30,7 @@ G_BEGIN_DECLS
struct _vte_termcap;
/* Create a new termcap structure. */
struct _vte_termcap *_vte_termcap_new(const char *filename);
struct _vte_termcap *_vte_termcap_new(char *filename);
/* Free a termcap structure. */
void _vte_termcap_free(struct _vte_termcap *termcap);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment