Pages

Monday, February 19, 2024

Haste makes waste

Sometimes I find that the old saying always gives me wisdom. Nowadays I had a chance to reaffirm it. Haste makes waste, so I detoured, and I could save time eventually.

The detail is as follows: I'm assigned to develop a feature to extract some data, which looks a piece of cake but not actually. I've got to extract both summary and "body" from single raw data, and it should be faster if I do it in one loop. However, considering existing data storage process I had to separate this to two separate thread - or, that was my first impression. Such that, I intentionally delayed the implementation being busy with whatever not associated with this for three days, which was expected to be done in one day, and I found far better alternative: use only one loop, and make subsections.

Personally I consider "incubation effect" as of the most importance. Already confirmed by the academia of psychology, you can see more and better for the given question when you encountered difficult question by doing something unrelated to the given issue for a while. The actual mechanism is not in agreement yet, but it is the job of the academia, and my job is using it with my thanks to those psychologists. :D

It's nothing, but I could reinforce my behavior with "I'm not wrong!", so I drop a line here.

급할수록 돌아가라

간혹 옛 성현들의 말씀 중에 틀린게 없다는걸 새삼 실감할 때가 있습니다. 최근에 그런걸 다시 한 번 느꼈는데...... 급할수록 돌아가라 하셔서 돌아갔더니만 궁극적으로 시간을 더 절약하게 되더군요.

상황은 대충 이렇습니다. 특정 데이터를 추출하는 새로운 기능을 만들어야 하는데,  겉으로 보기엔 간단하지만 실제로는 간단하지 않겠다는 생각이 들었습니다. 하나의 raw data에서 요약본과 메인 데이터 두 개를 추출해야 하는데, 반복문을 한 번만 돌리면 전체적으로는 수행이 더 빠르겠다는 생각이 들더군요. 하지만 기존의 데이터 저장 체계와 맞물려서 생각해보면 이걸 두 개의 스레드로 분리해야 할 수밖에 없는 상황이었는데...... 하루면 끝낼 일을, 일부러 사흘 정도 딴짓(?)을 하면서 시간을 질질 끌어보니 답이 나왔습니다. loop를 한 개로 놓고 데이터를 subsection 형태로 나누면 어떻게든 되곘더군요.

제가 평소 업무중 중요시하는 것 중 하나가 부화 효과입니다. 어려운 문제가 주어졌을 때 그 문제에 무작정 집중하지 말고, 그 문제와 전혀 관련없는 다른 일을 수행하다가 원래의 문제로 돌아오면 기존에는 보지 못했던 새로운 지평이 보인다는, 무려 심리학 실험을 통해 검증된 효과입니다. 왜 이러한 효과가 발생하느냐에 대해서는 아직 학계에서 갑론을박 중인 것으로 알고 있습니다만, 블랙박스의 내부 구조를 밝히는 것은 학계의 영역이고, 전 그저 쓰기만 하면 될 뿐이죠. :D

소소합니다만, 나는 틀리지 않았어! 하고 다시 한 번 확인하게 되는, 강화 요인 중 하나가 되었기에 끼적여봅니다.

Wednesday, September 6, 2023

Journey to the Vim IDE, and what I learned

It's a bit late, but I learned that Bram Mooleanaar, the very developer of Vim, has passed away last month. I sincerely show my humble respect to him and his legacy, the great text editor. Rest in peace.

I'm not sure whether this is a side effect, but I spent a few days on providing IDE-like environment in Vim. Since it is the second trial the result was satisfactory, but I conclduded that I'd continue to use Visual Studio Code(VS Code) and postponed to apply the environment to the production. There are some reasons:

  1. My hands got WAY TOO DIRTY on customization. Plugins collide here are there. There are some features which should be provided in plugins in Vim, while in VS Code that are embedded, and more plugins mean more breaking points, since they change the settings internally without considering the others.
  2. It's most people look over, but you can use VS Code without mouse for more than 95% of actions. It's not only hot keys but also command palette with fuzzy search support. Yes. It's not the only "gift" to Vimmers motto, "we don't need mouse!"

And personally, I recognized that I tried to make Vim-IDE as similar as VS Code. It's not only behave mswin but also tab movements, file explorer, etc. If that's the case, I'd prefer to remaining in VS Code, rather than make efforts to make Vim resemble VS Code.

 In my experience, the strength of of Vim is in editing, but not insertion. For example, you have commands like da", di', dt(, or the difference of O and o. And this is the very strength of modal editor, which provides a "special mode" only for editing. Yet for me, I spend most of the time in insertion, not in editing. And in doing that, what I use most is at best autocompletion. Vim is certainly wonderful job, but considering my use case most of them are unwanted. Jumping between normal mode and insert mode and enduring the inconvenience only for features which I'd use once a month at best is quite a nonsense.

Wrapping up, I'm sure that Vim is quite a treasure, but it doesn't fit to me, like someone said in Reddit, "VS Code versus Vim is not about what's better. They're just different and appeal to different type of people."

To my dear heavy Vim users, if you read this post, please don't be angry, but think of it as a practical case of "there's nothing like a shirt that fits to all."

So everyone, happy Vimming!

P.S:

Yet, I'm dissatisfied with performance drops due to the limit of VS Code brought by its structure(Javascript.......). Vim is a bit better, but Vimscript is still a script also, so they're anyway about the same to me. :P

Regarding this, finding an alternative for VS Code, I found Lapce(https://lapce.dev/), which is still pre-alpha but promising. If I have a chance, let me post for this.

Vim IDE로의 여행. 그리고 내가 배운 것

좀 늦었습니다만, 만으로 한달만에 Vim의 개발자인 Bram Moolenaar가 타개했다는 소식을 들었습니다. 위대한 텍스트 편집기의 개발자였던 그를 기억합니다. 편히 잠드시길.

그 여파인가......는 모르곘습니다만, 한 며칠정도를 Vim을 IDE화하는 작업에 쏟아붓고, 개인적으로 개발하던 프로젝트에 이를 적용해 보았습니다. 두 번째 시도라 그런지 결과는 꽤나 만족스러웠습니다만, 그럼에도 불구하고 Vim을 IDE로 사용하는 것은 보류하고, 기존에 쓰던 Visual Studio Code(이하 VS Code)를 계속 사용하기로 결정했습니다. 이유인즉슨:

  1. 커스터마이징에 손이 너무 많이 갑니다. 플러그인끼리의 충돌이 큽니다. VS Code에서는 기본적으로 지원하는 기능들조차 플러그인으로 적용해야 되는데, 이렇게 플러그인들이 쌓이다 보면 자기들끼리 설정을 변경하다가 충돌해서 프로그램이 오동작하는 경우가 꽤 생깁니다
  2. 사람들이 간과하는 부분 중 하나인데, VS Code도 95% 이상의 동작을 마우스 없이 사용할 수 있습니다. 단축키도 단축키이거니와, command pallette는 폼으로 있는게 아닐 뿐더러, fuzzy search까지 지원합니다. 요컨데, Vim의 "우리는 마우스 필요 없음!"이라는 주장이 VS Code에서도 똑같이 적용될 수 있다는 이야기지요.

그리고 개인적으로는, Vim을 IDE로 만들면서 VS Code와 유사하게 만들려고 시도를 하고 있더군요. behave mswin은 기본이고, 탭 이동이라던가, 파일 탐색기라던가 해서 진짜로 VS Code처럼 만들고 있었습니다. 이럴거면 그냥 VS Code 쓰고 말지 뭐하러 어렵게 Vim을 쓸까 하는 자괴감이 왔습니다.

제 생각에, Vim이 강점을 가지는 부분은 텍스트의 입력보다는 편집입니다. da", di', dt(같은 명령어라던가, O와 o의 차이라던가 하는 부분들이 있죠. 그리고 이건 modal editor가 가지는 필연적인 장점이기도 합니다. 이를테면, 텍스트 편집을 위한 전용 모드를 제공하기 때문에 편집에 강점을 가지죠. 그런데...... 저같은 경우 텍스트의 편집보다는 단순 입력에 훨씬 더 많은 시간을 쏟아붓습니다. 그리고 그 때 필요한 기능은 잘해봐야 자동완성 정도에요. Vim이 대단한 편집기인건 맞습니다만, 제 use case만 놓고 보면그 모든 기능 중 상당수는 쓸 일이 거의 없습니다. 한달에 한두번 쓰면 많이 쓸 것 같은 기능을 위해서 normal mode와 insert mode를 왔다갔다하면서 불편함을 감수하는건 주객이 전도된 일이 아닌가 합니다.

요컨데, Vim은 대단한 편집기이긴 하지만, 제 사용 성향에는 맞지 않는 것 같습니다. Reddit의 누군가가 "VS Code와 Vim은 누가 더 낫냐의 문제가 아니다. 그냥 다를 뿐이야. 다른 성향의 사람들에게 어필하는 것 뿐이라고"라고 말한게 잊혀지지 않는군요.

Vim heavy user 여러분, 만일 이 글을 보신다면 노여워하지 마시고, 그냥 "모든 사람에게 다 꼭 맞는 셔츠따위는 없다"는 오래된 격언의 적용 사례라고 생각해 주시면 좋겠습니다.

그럼 모두들, happy Vimming!

P.S:

다만, VS Code가 가지는 태생적 한계(Javascript 기반)로 인해 비교적 성능이 떨어지는 부분은 확실히 불만이 있습니다. Vim이 그런 의미에선 좀 더 낫긴 하지만, Vimscript 또한 스크립트 기반인걸 생각해보면 어떤 측면에서는 돗진이 갯진인지라......

관련해서 VS Code의 대체품을 찾던 중, Lapce라는, 아직 pre-alpha지만 가능성이 보이는 프로젝트를 발견했습니다(https://lapce.dev/). 기회가 되면 추후 이 프로그램에 대해서도 포스팅해 보도록 하지요.

Saturday, June 3, 2023

Vim vs. Neovim: it's yet immature

I had a chance to try Neovim, which is quite a hot potato among Vim users. As far as I know, Neovim is started as a fork of Vim to include some features rejected by Vim maintainers. What I know about Neovim is only two: they adopted Lua as their script language along with VimScript, and LSP client is included(after v0.4).

I was really not satisfied with LSP support from Vim, so I was curious about how Neovim native LSP works. Conclusion? Well...... Before jumping into LSP, it looks like their big file management is still living the era of Vim 7. The memory consumption of Vim 9 and Neovim 0.9 are quite similar, but while in Vim you could easily navigate from here to there without any delay from Vim 8, Neovim showed quite formiddable delay when I tried to jump from the start to end at once. Also, the initial loading was a bit slow....... Though others are unanimously saying that "it's GREAT!", for me it lacks some basics as a text editor. Also, Windows installer was a bit premature compared with vim-win32-installer.

Though LSP is important for me too, but my job frequently requires processing of multi-GB size text files, I think I'll reside on Vim for some time being.

P.S.1: My Main Development Environment
For your reference, I use Visual Studio Code as my main development environment. Vim is mainly used to edit some texts.

P.S.2: About Vim's LSP Plugins
Well, for me, CoC(https://github.com/neoclide/coc.nvim), the final boss(?), is isolating itself outside Vim ecosystem(if I have to run Node.js inside Vim, then I'd use Visual Studio Code instead), vim-lsp(https://github.com/prabirshrestha/vim-lsp) lacks support on how to show the diagnosis results, and ALE(https://github.com/dense-analysis/ale) doesn't show function signatures and code formatting is not supported....... Everything loses at least one core value from their stuff.

And today, I found this: https://github.com/yegappan/lsp

You've got to make your hands a bit dirty to configure(even you've got to register your LSP servers manually), but anyway it's editing some text files(:P). And with propre configuration it provides useful information as you see in the above screenshot. And one more thing: this is developed with Vim9Script - in other words, it doesn't work in Neovim.

P.S.3: Vim vs. Neovim - a Bridge You Can't Turn Back
While Neovim concentrates on Lua Vim made Vim9script, and Neovim announced they won't support Vim9script. I think this will be the marker of separation between these two projects. Personally it reminds me of the end of "full compatiblity" between MySQL 8 and MariaDB 10 due to differences in JSON support. The difference? In MySQL / MariaDB case the fork, MariaDB, shows better performance than MySQL, while in Vim / Neovim case the original, Vim, is better(at least to me).

Vim vs. Neovim: 아직은 좀 설익은 과일

최근 몇년간 Vim 사용자들에게 최고의 화두였던 Neovim을 잠깐 만져봤습니다. 제가 듣기로 Neovim은 Vim에서 이것좀 구현해주세요 했다가 "야 Vim은 지금 이 상태로 완전하거든?" 이란 말과 함께 퇴짜맞은 기능들을 넣은 fork로 출발한 프로젝트로 알고 있습니다. 주요한 특징이라면 스크립트 언어로 Lua를 채용했다거나, LSP를 내장했다거나(v0.4 이후) 정도로군요.

그러잖아도 Vim의 LSP 지원이 다들 영 마음에 안 들어서 좀 고민하던 차에, 내장 LSP가 어떻게 생겨먹었나 궁금해서 Neovim을 써봤습니다. 결론은 뭐....... LSP는 고사하고 대용량 파일 처리가 Vim 7 시절 그대로인 것 같더군요. 메모리 사용량은 Neovim 0.9나 Vim 9이나 비슷한데, Vim 8은 큰 파일도 날라댕기면서(......) 왔다갔다 하는게 가능한 반면 Neovim은 파일 처음에서 끝까지 가려면 한참을 기다려야 하더군요. 초기 로딩도 슬쩍 느리고...... 뭐랄까요. 써본 사람들은 다들 좋다 좋다 하는데 제게는 기본기가 좀 어설프다는 느낌이었습니다. Windows용 설치파일도 Vim Win32 Installer에 비하면 여러가지로 부족한 점이 많아 보였고요.

LSP도 LSP지만, 전 아무래도 대용량 텍스트(수 GB 이상)를 처리해야 되는 경우가 꽤 되어서, 당분간은 Vim에 계속 남아있게 될 것 같습니다.

P.S.1: 나의 메인 개발환경
아, 참고로 전 제 메인 개발환경으로 Visual Studio Code를 씁니다. Vim은 텍스트 편집이 주 용도에요.

P.S.2: Vim의 LSP 플러그인 이야기
일단 대충 끝판왕(......)인 CoC(https://github.com/neoclide/coc.nvim)는 Vim의 ecosystem 바깥에서 따로 놀고 있고(Vim 안에서 Node.js 돌릴거면 그냥 Visual Studio Code 쓰고 말죠), vim-lsp(https://github.com/prabirshrestha/vim-lsp)는 화면 표시 기능이 빈약하고, ALE(https://github.com/dense-analysis/ale)는 function signature가 표시가 안 될 뿐더러 code formatting 기능이 없고....... 뭐 다들 뭔가 한가지씩 필요한게 빠진 느낌이었습니다.

그러다가 오늘 괜찮은걸 발견했습니다. 이겁니다: https://github.com/yegappan/lsp


설정이 좀 번거롭긴 한데(LSP 서버도 수동으로 등록해야 됩니다), 그래봐야 텍스트 파일 편집이 전부이기도 하고, 잘 만져주면 위쪽 화면처럼 표시도 해줘서 보기가 엄청 편합니다. 그리고 결정적으로....... Vim9script로 만들었더군요. 옙. Neovim에서는 못 씁니다(......).

P.S.3: Vim vs. Neovim - 돌아올 수 없는 다리
Neovim이 Lua를 미는 동안 Vim은 Vim9script를 만들었고, Neovim은 Vim9script를 지원하지 않겠다고 선언했지요. 저는 이게 아마 둘의 갈림길이 될 것 같습니다. 개인적으로는 JSON 지원 방식의 차이로 인해 MySQL 8과 MariaDB 10 사이의 호환성이 갈라진게 떠오르는군요. 차이라면 MySQL / MariaDB는 fork본인 MariaDB가 MySQL보다 여러모로 더 좋은 성능을 보여주는 반면 Vim / Neovim은 원본인 (최소한 제 환경에서는) Vim이 Neovim보다 더 좋아보이는 것 같군요.

Tuesday, January 31, 2023

std::move = when std::optional should be launched

Recently I had a chance to take a look at Rust. When returning from a function Rust uses std::option to return either class A in success or class B in exception.

And I found out something similar in C++, namely std::optional. Most of C++ users argued that "why use  std::optional when we can fully make use of null pointers?" According to C++ Committee, it was due to minimize human errors. Then we can ask one thing: what kind of errors, then?

Let's take a look at the code below:

struct Insider {
    /* whatever great data structure */
};

struct anti_memory_leak {
    Insider *insider=nullptr;
    ~anti_memory_leak() {
        if(insider) delete insider;
    }
};

There's nothing special in this code. Since the class Insider can be used optionally, it can be allocated to heap. When anti_memory_leak is removed from memory, Insider object will be also removed in destructor so we have means for memory leak. We proved that we can do it without std::optional.

...... Did we?

Then let's investigate the code below:

void doSomethingGreat()
{
    anti_memory_leak object1;
    object1.insider=new Insider();

    std::vector<anti_memory_leak> vector1;
    vector1.push_back(std::move(object1));
    vector1.back().insider->value1=20; // CRASH!
}
 

This function crashed in the last line. Why? The reason is in the one line above. When you call  vector1.push_back(), even though you use std::move() object1 is destructed and recreated. And when destructing, the destructor of anti_memory_leak is called, and it surely remove insider from the heap. In other words, vector1.back().insider becomes a dangling pointer. It's kind of unfortunate, the result is the same if you use emplace_back() instead of push_back(). Anyway the application crash.

Now is the time std::optional should be used. If you declare an object with std::optional, the memory is initialized without allocating that optional object, and it is initialized when the optional object is explicitly created. Of course there's a small overhead, but say, it's also same for other similar(?) classes like std::shared_ptr. We have raw pointers, but to manage our precious heap more safely, we can automate some of the management so that we can solve potential incidents(including both memory leak and dangling pointer) more easily.

If we refactor the code above using std::optional, it will be like this:

struct Insider {
    int value1;
    /* whatever great data structure */
};

struct anti_memory_leak {
    std::optional<Insider> insider;
    ~anti_memory_leak() {
        if(insider) delete insider;
    }
};

void doSomethingGreat()
{
    anti_memory_leak object1;
    object1.insider=Insider();

    std::vector<anti_memory_leak> vector1;
    vector1.push_back(std::move(object1));
    vector1.back().insider.value1=20; // OK
}

If the flow of the code is simple it won't be a big problem. However, if the flow becomes anyway compilcated(e.g. multithreading), there should be chances to free memory or miss the chance when we have to, regardless of my intention. Let's think of std::optional as some kind of insurance policy; though we all agree that insurance fee is somewhat "waste of money"(lol), but we spend money to prepare for the worst? I think it's the same for std::optional.