On 9/24/16 2:17 PM, Hubert Schmid wrote:
> Configuration Information [Automatically generated, do not change]:
> Machine: x86_64
> OS: linux-gnu
> Compiler: gcc
> Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64'
> -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu'
> -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL
> -DHAVE_CONFIG_H -I. -I../. -I.././include -I.././lib -Wdate-time
> -D_FORTIFY_SOURCE=2 -g -O2 -fdebug-prefix-map=/build/bash-31ueiH/bash-4.4=.
> -fstack-protector-strong -Wformat -Werror=format-security -Wall
> -Wno-parentheses -Wno-format-security
> uname output: Linux vivo 4.7.0-1-amd64 #1 SMP Debian 4.7.4-2 (2016-09-19)
> x86_64 GNU/Linux
> Machine Type: x86_64-pc-linux-gnu
>
> Bash Version: 4.4
> Patch Level: 0
> Release Status: release
>
> Description:
> If the history file (`.bash_history`) starts with a timestamp
> (`HIST_TIMESTAMP_START`), and contains lines that have been written
> without timestamps, then reading the history file is (a) very slow
> because (b) consecutive lines without timestamps are merged into a
> single history entry with quadratic complexity.
>
> Apparently, this problem didn't exist in the previous version (4.3).
[...]
> Fix:
> Do not set `history_multiline_entries` to a non-zero value in
> `lib/readline/histfile.c`.
>
> Workaround without changing the code: Add a dummy history entry add
> the beginning of the history file without a timestamp. That has a
> similar effect as the code change, i.e. multi-line entries are not
> supported, and consecutive lines without timestamps will not be merged
> into a line history entry.
Try this patch and see if it improves the situation for this corner case.
Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU [email protected] http://cnswww.cns.cwru.edu/~chet/
*** ../bash-4.4/lib/readline/history.c 2015-12-28 13:50:31.000000000 -0500
--- lib/readline/history.c 2016-09-30 14:28:40.000000000 -0400
***************
*** 417,426 ****
{
HIST_ENTRY *hent;
! size_t newlen, curlen;
char *newline;
hent = the_history[which];
curlen = strlen (hent->line);
! newlen = curlen + strlen (line) + 2;
newline = realloc (hent->line, newlen);
if (newline)
--- 421,441 ----
{
HIST_ENTRY *hent;
! size_t newlen, curlen, minlen;
char *newline;
hent = the_history[which];
curlen = strlen (hent->line);
! minlen = curlen + strlen (line) + 2; /* min space needed */
! if (curlen > 256) /* XXX - for now */
! {
! newlen = 512; /* now realloc in powers of 2 */
! /* we recalcluate every time; the operations are cheap */
! while (newlen < minlen)
! newlen <<= 1;
! }
! else
! newlen = minlen;
! /* Assume that realloc returns the same pointer and doesn't try a new
! alloc/copy if the new size is the same as the one last passed. */
newline = realloc (hent->line, newlen);
if (newline)