New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Foldexpr_markdown very slow for some documents #162

Closed
khughitt opened this Issue Jan 6, 2015 · 7 comments

Comments

Projects
None yet
5 participants
@khughitt

khughitt commented Jan 6, 2015

When working on a mixed Markdown/LaTeX document, I noticed after a while the performance of very basic actions like deleting a word or pasting text was becoming very slow.

I profiled vim to see what the culprit was, and it turned out the be the vim-markdown (commit 091091f from 2015/01/02) Foldexpr_markdown function. After just a few seconds of profiling and performing basic text manipulation operations on a paragraph of plain-text, Foldexpr_markdown was called over 100,000 times:

FUNCTION  Foldexpr_markdown()                                                                  
Called 107204 times                                                                            
Total time:   3.945203                                                                         
 Self time:   3.945203                                                                         

count  total (s)   self (s)                                                                    
107204              0.177798     if (a:lnum == 1)                                              
                                    let l0 = ''                                                
                                else                                                           
107204              0.371518         let l0 = getline(a:lnum-1)                                
107204              0.095889     endif                                                         

107204              0.270002     let l1 = getline(a:lnum)                                      

107204              0.316180     let l2 = getline(a:lnum+1)                                    

107204              0.444422     if  l2 =~ '^==\+\s*'                                          
                                    " next line is underlined (level 1)                        
                                    return '>1'                                                
                                elseif l2 =~ '^--\+\s*'                                        
                                    " next line is underlined (level 2)                        
   72              0.000086         return '>2'                                                
                                elseif l1 =~ '^#'                                              
                                    " don't include the section title in the fold              
                                    return '-1'                                                
                                elseif l0 =~ '^#'                                              
                                    " current line starts with hashes                          
                                    return '>'.matchend(l0, '^#\+')                            
                                else                                                           
                                    " keep previous foldlevel                                  
107132              0.097830         return '='                                                
                                endif                                  

To be sure that this was indeed the issue, I disabled vim-markdown folding using let g:vim_markdown_folding_disabled=1 and the issue went away.

Unfortunately I am not sure how to reproduce the issue outside of the larger document I am working on, so I cannot pinpoint the cause of the problem.

The document is not all that special, except that is contains a couple simple LaTeX equations and images. The image blocks are the most complex bit of LaTeX, and they look something like:

\begin{wrapfigure}{r}{0.5\textwidth}                                                           
\begin{framed}\raggedleft%\centering                                                           
  \vspace{-20pt}                                                                               
  \begin{center}                                                                               
    \includegraphics[width=1\textwidth]{images/image}                       
  \end{center}                                                                                 
  \vspace{-20pt}                                                                               
  \caption{\textbf{text...}  text..
    more text...}
  \vspace{-10pt}                                                                               
\end{framed}                                                                                   
\end{wrapfigure}

Vim version:
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Dec 27 2014 04:46:10)
Included patches: 1-560

I'm sorry I can't provide a more reproducible example. Hopefully this might give you some ideas about the underlying issue, or perhaps someone else with the same problem can help to clarify.

Let me know if there is anything else I can do to help track down the issue.

@retrography

This comment has been minimized.

retrography commented Sep 23, 2015

@khughitt Are you working on a Pandoc document or similar with a front matter? Is it possible that you have an unclosed YAML front matter in your document. Pandoc, for instance, has a weird front matter that opens with --- and closes with ..., and this plugin won't recognize that. At least for me this was the issue. Even if this is not the case for you, you may want to check to see if there is something in your text that this plugin considers as opening a block, and that is not followed by a bock-closing sign.

@khughitt

This comment has been minimized.

khughitt commented Sep 25, 2015

@retrography I am indeed using Pandoc to convert the Markdown to PDF, and am including a YAML header. As far as I can tell though, it should be properly closed.

The YAML block for the document is:

---
bibliography: references.bib
header-includes:
   - \usepackage[font=small,labelfont=bf]{caption}
   - \usepackage{wrapfig}
   - \usepackage{framed}
   - \pagenumbering{gobble}
output:
    pdf_document
---

There is one other instance in the document of a long string of dashes used to create a header item (-----------), and I found one instance of '...' in a comment in the document.

It's been a while since I worked on that document, however, and when I tried to reproduce the issue just now I was unable to.

I'll re-enable folding though and let you know if I run into the problem again.

Feel free to close this issue in the meantime if you would prefer.

Thanks!

@shirosaki shirosaki closed this Jan 18, 2016

@alexconst

This comment has been minimized.

Contributor

alexconst commented Feb 1, 2016

Is there any workaround for this?

I'm writing a small script to help me with pandoc-markdown-jekyll (it parses the whole file while making changes along the way with setline) but Foldexpr_markdown takes too much time (~ 15 seconds for a ~ 750 lines file).
And it doesn't matter if the frontmatter closure is set to '...' or '---'.
I also tried let g:vim_markdown_folding_disabled = 1 in my script but no luck.

The only workaround I found so far was using let g:vim_markdown_folding_disabled = 1 in .vimrc. But this disables folding altogether.

BTW, Pandoc's YAML closure is valid. More info on this at jgm/pandoc#2668

@shirosaki

This comment has been minimized.

Collaborator

shirosaki commented Feb 1, 2016

:setl foldexpr=0 to disable folding of current buffer.
let g:vim_markdown_folding_disabled = 1 at runtime doesn't work.

@alexconst

This comment has been minimized.

Contributor

alexconst commented Feb 1, 2016

Thanks! That solved it.

Just wondering if there is a way to save and restore the foldexpr value in vimscript?
I can save the value with let orgfoldexpr=&foldexpr but I'm unable to restore it afterwards.

@shirosaki

This comment has been minimized.

Collaborator

shirosaki commented Feb 2, 2016

&foldexpr seems to be string.
setl foldexpr=eval(orgfoldexpr) restores the string value.

@alexconst

This comment has been minimized.

Contributor

alexconst commented Feb 2, 2016

Works like a charm. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment