Subject: Re: bug#56342: TRAMP (sh) issues way too many commands, thus being very slow over high-ping networks

From: Paul Pogonyshev <[email-masked]>
Date: Mon, 1 Aug 2022 22:20:41 +0200

> As said, I live in a pretty good connected LAN. remote commands do not
> result in heavy performance degradations, compared with the rest of
> Elisp computing.

Understood, but I propose to adopt a different benchmark: number of
remote commands.  As soon as you are not in a LAN, even not when using
a particularly slow network, this becomes an order or two of magnitude
more important than everything else.  E.g. with slightly slower
commands or particularly inefficient Elisp you can make it 2-10 ms
slower for everyone.  But with unoptimized command flow (i.e. more
remote commands) it can be 100-500 ms slower, though not for everyone,
but people using this over non-LAN.  I think in such cases extremes
are more important than the average.

> > On the other hand, refreshing a remote-tracking Magit (Emacs Git
> > interface) buffer doesn't feel any faster than before. Logs also
> > suggest that number of commands that tramp send stays as before (43).
> > Some commands are certainly excessive, e.g. it repeats `test -d [...]
> > 2>/dev/null; echo tramp_exit_status $?' 4 times for the same directory
> > (intermixed with other commands), suggesting that Tramp doesn't cache
> > the result. Three times it issues `test -r ...' for the same
> > directory, the source checkout root. Most other commands cannot be
> > generically skipped by Tramp though, this would rather depend on
> > Magit.
>
> Caches are problematic. They are limited to 10 seconds by default, did
> you try to increase that number?

Yes, `remote-file-name-inhibit-cache' is now 600 here.

> And directories are also problematic for caches. As soon as something
> changes there (creation or deletion of a file, for example), the cached
> values of the directory must be flushed.

Yeah, I suppose Tramp has no generic way to know that Magit issues
reading commands.  Can we devise a generic interface that would tell
Tramp: "Commands within this block will not modify file system",
e.g. with let-binding some variable?

In general, it feels like Tramp flushes its caches too often or maybe
doesn't even cache certain things at all.  I.e. it's not about those
10 seconds (following your advice I have even increased that).  It's
that while serving one user-level command here (i.e. within 3 seconds
at most), it can issue the same remote command several times, thus
not reusing previous results.

E.g. in the traces you have attached this can be seen.  The following
two commands repeat twice:

| | | 4 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef" nil
"/tmp/tramp.qgnQ01" nil) "\\readlink --canonicalize-missing
/tmp/tramp.qgnQ01 2>/dev/null; echo tramp_exit_status $?")
...
| | | 4 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef" nil
"/tmp/tramp.qgnQ01" nil) "\\readlink --canonicalize-missing
/tmp/tramp.qgnQ01 2>/dev/null; echo tramp_exit_status $?")

and

| | | | | 6 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef"
nil "/tmp/tramp.qgnQ01" nil) "tramp_stat_file_attributes /tmp/tramp.qgnQ01
2>/dev/null; echo tramp_exit_status $?")
...
| | | | | 6 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef"
nil "/tmp/tramp.qgnQ01" nil) "tramp_stat_file_attributes /tmp/tramp.qgnQ01
2>/dev/null; echo tramp_exit_status $?")

Paul

On Tue, 26 Jul 2022 at 19:51, Michael Albinus <[email-masked]>
wrote:

> Paul Pogonyshev <[email-masked]> writes:
>
> Hi Paul,
>
> >> Combining stat and readlink into one remote command have even slowed
> >> down the machinery. Likely, because it isn't needed always, but it
> >> always consumes more time to compute both on the remote side, and to
> >> read all the results.
> >
> > Well, that's hard to believe. I mean, it is understandable that
> > `readlink' (whatever Elisp call results in that shell command) is not
> > often needed, but how long can that take on a modern computer, 1 ms?
> > It might be that we evaluate performance changes differently. I care
> > more about worst cases (since they affect me directly, yeah) and not
> > so much if Tramp becomes 1 ms slower "per user-visible operation" on
> > average.
>
> As said, I live in a pretty good connected LAN. remote commands do not
> result in heavy performance degradations, compared with the rest of
> Elisp computing.
>
> > I tested it a bit now. Initially mentioned usecase
> > (`insert-file-contents', but only a file part, not the whole file)
> > appears to be considerably faster after the changes (hard to say,
> > feels like 30-50% faster).
>
> Oh, good. In my environment it was something about 5%.
>
> > The connection log says that number of
> > commands is 10 now, with the originally mentioned list heavily
> > changed. However, there must still be space for improvement, e.g. `M-x
> > occur tramp-send RET' suggests there are outright duplicated commands
> > now:
>
> Pretty sure there's still place for improvements!
>
> > On the other hand, refreshing a remote-tracking Magit (Emacs Git
> > interface) buffer doesn't feel any faster than before. Logs also
> > suggest that number of commands that tramp send stays as before (43).
> > Some commands are certainly excessive, e.g. it repeats `test -d [...]
> > 2>/dev/null; echo tramp_exit_status $?' 4 times for the same directory
> > (intermixed with other commands), suggesting that Tramp doesn't cache
> > the result. Three times it issues `test -r ...' for the same
> > directory, the source checkout root. Most other commands cannot be
> > generically skipped by Tramp though, this would rather depend on
> > Magit.
>
> Caches are problematic. They are limited to 10 seconds by default, did
> you try to increase that number? VC related commands are also
> problematic, Emacs tests different VC's for availability. It is always a
> good idea to reduce the number of VC backends. If you completely trust
> in magit, you shall deactivate Emacs' vc.el. Something like (setq
> vc-handled-backends nil) should help.
>
> And directories are also problematic for caches. As soon as something
> changes there (creation or deletion of a file, for example), the cached
> values of the directory must be flushed.
>
> I propose we try step by step. That is, we investigate typical code
> snippets, and see what Tramp does. Case by case.
>
> The Tramp debug buffer is a little bit noisy. So you could do
>
> (progn
>   (trace-function-background 'tramp-send-command)
>   (trace-function-background 'tramp-file-name-handler))
>
> By this, only the calls of tramp-send-command (go remote) and
> tramp-file-name-handler (any invocation of Tramp) are traced. The latter
> is important to know, what has triggered a given remote command.
>
> Starting with your initial example
>
> (with-temp-buffer
>   (insert-file-contents "/ssh:detlef:.emacs" nil 100 nil))
>
> I get the *trace-output* buffer as appended. Let's study this first, and
> see, what could be done in order to improve this case. Obviously, most
> of the commands are about the temporary file /tmp/tramp.qgnQ01, which is
> superfluous. I'll check whether handling temporary files could be
> handled better.
>
> When we're happy with this example, let's go to the next example.
>
> > Paul
>
> Best regards, Michael.
>
> PS: Next 2 or 3 days I'm kind of absent: my granddaughter will visit
> us. Sorry, but you know: priorities :-)
>
> ======================================================================
> 1 -> (tramp-file-name-handler expand-file-name "/ssh:detlef:.emacs" nil)
> 1 <- tramp-file-name-handler: "/ssh:detlef:/home/albinus/.emacs"
> ======================================================================
> 1 -> (tramp-file-name-handler insert-file-contents
> "/ssh:detlef:/home/albinus/.emacs" nil 2 4 nil)
> | 2 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/home/albinus/.emacs" nil)
> | 2 <- tramp-file-name-handler: "/ssh:detlef:/home/albinus/.emacs"
> | 2 -> (tramp-file-name-handler expand-file-name "tramp."
> "/ssh:detlef:/tmp")
> | 2 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp."
> | 2 -> (tramp-file-name-handler expand-file-name "/ssh:detlef:/tmp/tramp."
> "/tmp/")
> | 2 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp."
> | 2 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | 2 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | 2 -> (tramp-file-name-handler write-region "" nil
> #1="/ssh:detlef:/tmp/tramp.qgnQ01" nil silent #1# excl)
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-truename
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | 4 -> (tramp-file-name-handler file-remote-p
> "/ssh:detlef:/tmp/tramp.qgnQ01" localname nil)
> | | | | 5 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 <- tramp-file-name-handler: "/tmp/tramp.qgnQ01"
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 -> (tramp-file-name-handler file-remote-p
> "/ssh:detlef:/tmp/tramp.qgnQ01" localname nil)
> | | | | 5 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 <- tramp-file-name-handler: "/tmp/tramp.qgnQ01"
> | | | 4 -> (tramp-file-name-handler file-remote-p
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil nil)
> | | | | 5 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:"
> | | | 4 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef" nil
> "/tmp/tramp.qgnQ01" nil) "\\readlink --canonicalize-missing
> /tmp/tramp.qgnQ01 2>/dev/null; echo tramp_exit_status $?")
> | | | | 5 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef"
> nil "/tmp/tramp.qgnQ01" nil) "echo are you awake" t t)
> | | | | 5 <- tramp-send-command: nil
> | | | 4 <- tramp-send-command: 39
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 -> (tramp-file-name-handler file-symlink-p
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | | 5 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | | 5 -> (tramp-file-name-handler file-attributes
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | | | 6 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | | 6 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | | | 6 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef"
> nil "/tmp/tramp.qgnQ01" nil) "tramp_stat_file_attributes /tmp/tramp.qgnQ01
> 2>/dev/null; echo tramp_exit_status $?")
> | | | | | 6 <- tramp-send-command: 25
> | | | | 5 <- tramp-file-name-handler: nil
> | | | 4 <- tramp-file-name-handler: nil
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-exists-p
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | 3 <- tramp-file-name-handler: nil
> | | 3 -> (tramp-file-name-handler file-locked-p
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | 4 -> (tramp-file-name-handler make-lock-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | 4 <- tramp-file-name-handler: nil
> | | 3 <- tramp-file-name-handler: nil
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-attributes
> "/ssh:detlef:/tmp/tramp.qgnQ01" integer)
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 <- tramp-file-name-handler: nil
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-attributes
> "/ssh:detlef:/tmp/tramp.qgnQ01" integer)
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 <- tramp-file-name-handler: nil
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-acl "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | 3 <- tramp-file-name-handler: nil
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-selinux-context
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | 3 <- tramp-file-name-handler: (nil nil nil nil)
> | | 3 -> (tramp-file-name-handler file-name-nondirectory
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | 3 <- tramp-file-name-handler: "tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-remote-p
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil nil)
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:"
> | | 3 -> (tramp-file-name-handler lock-file
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | 4 -> (tramp-file-name-handler file-locked-p
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | | 5 -> (tramp-file-name-handler make-lock-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | | 5 <- tramp-file-name-handler: nil
> | | | 4 <- tramp-file-name-handler: nil
> | | | 4 -> (tramp-file-name-handler make-lock-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | 4 <- tramp-file-name-handler: nil
> | | | 4 -> (tramp-file-name-handler make-lock-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | 4 <- tramp-file-name-handler: nil
> | | 3 <- tramp-file-name-handler: nil
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-modes
> "/ssh:detlef:/tmp/tramp.qgnQ01" nofollow)
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 -> (tramp-file-name-handler file-attributes
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | | 5 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 <- tramp-file-name-handler: nil
> | | 3 <- tramp-file-name-handler: nil
> | | 3 -> (tramp-file-name-handler file-name-nondirectory
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | 3 <- tramp-file-name-handler: "tramp.qgnQ01"
> | | 3 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef" nil
> "/tmp/tramp.qgnQ01" nil) "base64 -d -i >/tmp/tramp.qgnQ01
> <<'b03f0306a9a1e716a81252ccc4134b92' 2>/dev/null; echo tramp_exit_status
> $?\nb03f0306a9a1e716a81252ccc4134b92")
> | | 3 <- tramp-send-command: 21
> | | 3 -> (tramp-file-name-handler file-name-directory
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/"
> | | 3 -> (tramp-file-name-handler expand-file-name "/ssh:detlef:/tmp/" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/"
> | | 3 -> (tramp-file-name-handler directory-file-name "/ssh:detlef:/tmp/")
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp"
> | | 3 -> (tramp-file-name-handler file-modes "/ssh:detlef:/tmp" nil)
> | | | 4 -> (tramp-file-name-handler expand-file-name "/ssh:detlef:/tmp"
> nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp"
> | | | 4 -> (tramp-file-name-handler file-attributes "/ssh:detlef:/tmp")
> | | | | 5 -> (tramp-file-name-handler expand-file-name "/ssh:detlef:/tmp"
> nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp"
> | | | | 5 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef"
> nil "/tmp" nil) "tramp_stat_file_attributes /tmp 2>/dev/null; echo
> tramp_exit_status $?")
> | | | | 5 <- tramp-send-command: 129
> | | | 4 <- tramp-file-name-handler: (t 30 0 0 (25305 58381 0 0) (25312
> 7412 0 0) (25312 7412 0 0) 135168 "drwxrwxrwt" t 3801089 (-1 . 2))
> | | 3 <- tramp-file-name-handler: 1023
> | | 3 -> (tramp-file-name-handler tramp-set-file-uid-gid
> "/ssh:detlef:/tmp/tramp.qgnQ01" 1000 1000)
> | | | 4 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef" nil
> "/tmp/tramp.qgnQ01" nil) "chown 1000:1000 /tmp/tramp.qgnQ01")
> | | | 4 <- tramp-send-command: 1
> | | 3 <- tramp-file-name-handler: 1
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" "~/")
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler set-file-acl
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 <- tramp-file-name-handler: nil
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" "~/")
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler set-file-selinux-context
> "/ssh:detlef:/tmp/tramp.qgnQ01" (nil nil nil nil))
> | | 3 <- tramp-file-name-handler: nil
> | | 3 -> (tramp-file-name-handler unlock-file
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | 4 -> (tramp-file-name-handler make-lock-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | 4 <- tramp-file-name-handler: nil
> | | 3 <- tramp-file-name-handler: nil
> | 2 <- tramp-file-name-handler: nil
> | 2 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef" nil
> "/home/albinus/.emacs" nil) "dd bs=1 skip=2 if=/home/albinus/.emacs count=2
> of=/tmp/tramp.qgnQ01")
> | 2 <- tramp-send-command: 72
> | 2 -> (tramp-file-name-handler file-local-copy
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | 3 -> (tramp-file-name-handler file-truename
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | 4 -> (tramp-file-name-handler file-remote-p
> "/ssh:detlef:/tmp/tramp.qgnQ01" localname nil)
> | | | | 5 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 <- tramp-file-name-handler: "/tmp/tramp.qgnQ01"
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 -> (tramp-file-name-handler file-remote-p
> "/ssh:detlef:/tmp/tramp.qgnQ01" localname nil)
> | | | | 5 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 <- tramp-file-name-handler: "/tmp/tramp.qgnQ01"
> | | | 4 -> (tramp-file-name-handler file-remote-p
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil nil)
> | | | | 5 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:"
> | | | 4 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef" nil
> "/tmp/tramp.qgnQ01" nil) "\\readlink --canonicalize-missing
> /tmp/tramp.qgnQ01 2>/dev/null; echo tramp_exit_status $?")
> | | | 4 <- tramp-send-command: 39
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 -> (tramp-file-name-handler file-symlink-p
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | | 5 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | | 5 -> (tramp-file-name-handler file-attributes
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | | | 6 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | | 6 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | | | 6 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef"
> nil "/tmp/tramp.qgnQ01" nil) "tramp_stat_file_attributes /tmp/tramp.qgnQ01
> 2>/dev/null; echo tramp_exit_status $?")
> | | | | | 6 <- tramp-send-command: 148
> | | | | 5 <- tramp-file-name-handler: (nil 1 1000 1000 (25312 7412 0 0)
> (25312 7412 0 0) (25312 7412 0 0) 2 "-rw-rw-r--" nil 3821258 (-1 . 2))
> | | | 4 <- tramp-file-name-handler: nil
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-name-nondirectory
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | 3 <- tramp-file-name-handler: "tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-attributes
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 <- tramp-file-name-handler: (nil 1 1000 1000 (25312 7412 0 0) (25312
> 7412 0 0) (25312 7412 0 0) 2 "-rw-rw-r--" nil 3821258 (-1 . 2))
> | | 3 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef" nil
> "/tmp/tramp.qgnQ01" nil) "base64 </tmp/tramp.qgnQ01 2>/dev/null; echo
> tramp_exit_status $?")
> | | 3 <- tramp-send-command: 26
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-file-name-handler file-modes
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | 4 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 -> (tramp-file-name-handler file-attributes
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | | | | 5 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | | | 5 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | | 4 <- tramp-file-name-handler: (nil 1 1000 1000 (25312 7412 0 0)
> (25312 7412 0 0) (25312 7412 0 0) 2 "-rw-rw-r--" nil 3821258 (-1 . 2))
> | | 3 <- tramp-file-name-handler: 436
> | 2 <- tramp-file-name-handler: "/tmp/tramp.6ce5x9.qgnQ01"
> | 2 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | 2 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | 2 -> (tramp-file-name-handler file-directory-p
> "/ssh:detlef:/tmp/tramp.qgnQ01")
> | 2 <- tramp-file-name-handler: nil
> | 2 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | 2 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | 2 -> (tramp-file-name-handler delete-file
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 -> (tramp-file-name-handler expand-file-name
> "/ssh:detlef:/tmp/tramp.qgnQ01" nil)
> | | 3 <- tramp-file-name-handler: "/ssh:detlef:/tmp/tramp.qgnQ01"
> | | 3 -> (tramp-send-command (tramp-file-name "ssh" nil nil "detlef" nil
> "/tmp/tramp.qgnQ01" nil) "rm -f /tmp/tramp.qgnQ01 2>/dev/null; echo
> tramp_exit_status $?")
> | | 3 <- tramp-send-command: 21
> | 2 <- tramp-file-name-handler: t
> 1 <- tramp-file-name-handler: ("/ssh:detlef:/home/albinus/.emacs" 2)
>