Looking for Participants for User Survey on ocaml.org Package Documentation and Learn Area

I find the Learn page particularly hard to navigate (Mozilla Firefox 91.13.0esr on Debian 11):

Thank you for including the browser version - this is quite different from what I see on all the browsers I have installed and clearly not what was intended here. Are there any nonstandard settings (e.g. font size) used?

I created an issue here Learn Page displays Mobile/Tablet Layout on Mozilla Firefox 91.13.0esr on Debian 11 路 Issue #822 路 ocaml/ocaml.org 路 GitHub for the problem that your browser seems to display the tablet/mobile layout of the page, and Height of the Hero-Links on the Learn Page on md- and below screens 路 Issue #823 路 ocaml/ocaml.org 路 GitHub for the way too tall hero links. (I remember @dbuenzli also reporting this height problem to me, but it fell off my plate. Good that we鈥檙e getting to it now.)

This is curious actually, because ocamlformat clearly has a nice readme that I would have expected to be reproduced on the package overview page (that the link goes to). Some package overview pages display an extremely short "Description" 路 Issue #825 路 ocaml/ocaml.org 路 GitHub

Clearly, the intention of ocamlformat here is to link directly to the documentation. After we fix the URL structure to allow people to link to the latest version of the documentation of a package (Adding latest url to package links by SaySayo 路 Pull Request #793 路 ocaml/ocaml.org 路 GitHub), the link on the GitHub repository鈥檚 README can be updated to go directly to the documentation.

I also agree with you that the documentation link should be much more prominent in order to easily find and click it. Package Documentation Link should be more obvious and clickable 路 Issue #826 路 ocaml/ocaml.org 路 GitHub

For comparison, this is what the original page looks like:

It may be a better experience to disable Brave鈥檚 speed reader mode (https://twitter.com/brave/status/1559235636464418816) for these pages as it is not a high-priority problem compared to more pressing issues.

1 Like

please don鈥檛 do that, it will have the same effect 鈥渢hey don鈥檛 know what they are talking about鈥. Memoization is a useful trick in general, Multicore is great technology, I鈥檓 just advising against choosing a too simple example, because for this particular example a much simpler and faster solution exist.

(every mathematician knows that a linear recurrence of order 2 can be transformed into a recurrence of order 1 (hence linear complexity) acting on pairs)

For instance here, just use let fib n = let rec loop n = if n < 1 then (0, 1) else let x, y = loop (n-1) in y, (x+y) in snd (loop n);;

Of course, the memoization is also O(n), but it鈥檚 like a big hammer when there is a much more elegant solution, and I鈥檓 sure ocamlers like fast and elegant solutions :wink:

1 Like

For lightweight concurrent processes (those are provided separately in Domainslib though鈥), channel communication and message passing, atoms/symbols (well-typed thanks to polymorphic variants!), etc鈥 I think something like erlang鈥檚 ping-pong would turn some heads.
The problem is 1. we will have to rely on domainslib, and 2. although I imagine we鈥檙e as performant, if not more, than erlang in terms of lightweight processes cost and runtime efficiency (perhaps not scheduling, their runtime is of course more battle-tested), our concurrency prims don鈥檛 look as nice currently. There鈥檚 more to write by hand than just:

ping(0, Pong_PID) ->
    Pong_PID ! finished,
    io:format("ping finished~n", []);

ping(N, Pong_PID) ->
    Pong_PID ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    ping(N - 1, Pong_PID).

pong() ->
    receive
        finished ->
            io:format("Pong finished~n", []);
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pong()
    end.

start() ->
    Pong_PID = spawn(tut15, pong, []),
    spawn(tut15, ping, [3, Pong_PID]).

so in the end it might not look good from a marketing perspective.

1 Like

I think this implementation makes sense though, fib (n-1) in this definition is roughly 鈥渉alf the work鈥 of fib n.
This implementation of fib is the one doing the most work (of the usual definitions you see around), and also the one with the most visible slowdown, so using it expresses concisely (and elegantly IMO) the idea of 鈥渟plitting a heavy workload on multiple CPUs鈥.

It would make way less sense it you were using it for just advertising the language of course, not multicore capabilities.

1 Like

Thanks @hyphenrf, @sanette @benjamin-thomas for the discussion on the playground example. Here鈥檚 a PR to improve the playground example by making it clearer that (currently) the point is to show off the new multicore support. Adding the more efficient single threaded implementation in the comment to encourage beginners to think about the performance implications of their code: minor changes to the playground example by sabine 路 Pull Request #831 路 ocaml/ocaml.org 路 GitHub.

ETA: after the novelty of OCaml 5 wears off, there鈥檚 space for a more beginner-focused example to occupy this space.

1 Like

I鈥檓 not a specialist of parallel computing, but it seems to me that computation on large vectors (or matrices) is a predilection area. I just wrote a (probably too) simple implementation of a dot product, and on my laptop it鈥檚 already quite faster than the sequential loop:

let num_domains = 2

(** Sequential implementation of the dot product of the sub-arrays of
   [a] and [b] of length [l] starting at index [i]. *)
let dot_seq a b i l =
  let x = ref 0. in
  for j = i to i+l-1 do
    x := !x +. a.(j) *. b.(j)
  done;
  !x

(** Dot product of [a] and [b]. Parallel implementation, which simply
    splits the array into [num_domains] subarrays, each of which is
    computed sequentially by [dot_seq], and finally combines the
    results to sum them. *)
let dot a b =
  let n = Array.length a in
  assert (n = Array.length b);
  let l = n / num_domains in
  let rec loop i d spawns =
    if d = 0 then spawns
    else let l = if d = 1 then n - i else l in
         loop (i+l) (d-1)
           ((Domain.spawn (fun () -> dot_seq a b i l)) :: spawns) in
  loop 0 num_domains []
  |> List.map Domain.join
  |> List.fold_left ( +. ) 0.

The tests and results are here: dot.ml 路 GitHub

I鈥檓 surprised that the performance gain is significantly better for bytecode than for nativecode: is there any simple reason for this?

2 Likes

I鈥檓 assuming the OCaml playground is for beginners. If so, then it would be tremendously helpful if the OCaml playground example worked on beginners鈥 computers. For example, the Domainslib used in the example is not generally available for a beginner to use on Windows. Domainslib requires OCaml 5, and that is only available for mingw Windows, which is not something to ask beginners to install.

Someone can correct me if I鈥檓 wrong but there is no backport of Domainslib to 4.x (if that even made sense, which is doubtful).

2 Likes

From what I see in other languages and frameworks: Playgrounds serve these purposes:

(1) entice beginners to try out basic examples right in their browser so they do not have to install anything
(2) help people share smallish code snippets in forums/chats in such a way that someone else can help them debug, or
(3) as a way to quickly answer someone else鈥檚 question with some code snippet (which is confirmed to run because they used the playground to write it)
(4) for package authors to provide code examples that potential users of the package can tinker with (requires a playground that can import any packages).

1 Like

Oh that makes sense. That is probably why the Rust playground is just a prototypical Hello World example.

Still, have you seen official code examples on a playground where it can鈥檛 be run on a large percentage of the viewers鈥 computers?

My two cents would be:

  • a one-liner program like let () = print_endline "Hello, world!";; by default
  • have a URL parameter for the playground like https://ocaml.org/play?template=parallel-domains-example that can be used in all the OCaml 5 (ex. 鈥淭ry it now鈥) pages. Obviously that template URL parameter (or something similar) would control what was populated in the playground, and that is unplanned extra work.
  • the parallel-domains-example could come with a brief comment at the top (* You would need OCaml 5 for this example on a PC. That is available for many platforms at https://ocaml.org/news/ocaml-5.0, with more platforms coming soon. *).
2 Likes

For comparison, the ReScript playground has a tiny React component for their default. Cool thing about that is it shows a strength of ReScript, but is also simple. Now, I鈥檓 not sure what the analog of that in the OCaml world would be, but it may be cool to to try and think of some 鈥渒iller feature鈥 to show off. (Not sure which killer feature, but still worth thinking about.)

A dot product is memory-bound: 1 cold memory access per arithmetic operation. So, increasing the number of domains will not make it faster. Bytecode interpretation, however, is compute-bound. So, you will get a nice linear speedup, until either it becomes as fast as native code execution (and thus memory-bound) or you saturate the cores of your computer.

but I do have a speedup for native code as well.

Keep in mind that, at each loop iteration, your code tests twice whether the array accesses are in bound and whether the domain needs to synchronize with the other domains to perform a garbage collection. Even if all these tests are perfectly predicted by the processor, their sheer amount still mess with the speculative execution, which means that your core does not run as fast as it theoretically could (e.g., what you would get with the same code written in C). So, the memory can keep up, and you still experience a small speedup by going from one domain to two domains.

I am pretty sure that, if you use four domains instead (assuming you have at least four cores), you will not see any additional speedup for native code, while you will still see a 2x speedup for bytecode.

By the way: In case someone who has time at their hands to contribute reads here:

You can always reach out to any of the maintainers on GitHub - ocaml/ocaml.org: The official OCaml website. with a feature/improvement that you want to contribute and we鈥檒l be happy to guide you, pair program, and review speedily. For bigger contributions, do always approach us, because sometimes it is not obvious what exactly is already being worked on behind the scenes.

Not enjoying the content? Wanting to add an academic institution that uses OCaml to the list? Want to post an open OCaml position at your company? You can
(1) fork the GitHub repository, create a branch with your suggested changes and open a pull request, or
(2) open an issue on the GitHub repository, or
(3) send an email. :slight_smile:

In contrast to publishing your own OCaml package, this is a much more casual way of contributing to the success of OCaml: maintenance is taken care of, you can focus solely on improving or adding features and content! :grin:

2 Likes

thanks for the explanation!

Here鈥檚 the promised update on what kind of feedback we got out of the user survey. I tried to distill as best as I could, there was so much feedback! :slight_smile:

We have responses from 20 people in total, and a lot of those have volunteered to be interviewed by Claire. So this is excellent! In the interest of getting a good overview of the userbase, Claire will select people and send out invites.

Summary:

17 people are using OCaml for personal projects, 7 for business purposes, and 6 use OCaml for research purposes.

We have a good mix of junior and senior software development and research roles, as well as organisations of varying sizes and a broad mix of tasks people work on. I do not list these individually.

Pain points / package documentation:

Ideas/suggestions package documentation:

  • Tree navigation should be improved, e.g. library vs toplevel module should be consolidated, hiding other libraries when going down into a module should be removed
  • Index for declarations (values, types, exceptions, etc.) of a module could be displayed in place of the empty TOC / appended to the TOC

Problems with content and documentation writing experience:

  • Lack of example code, quality of documentation on package docs displayed on ocaml.org
  • UI/UX of odoc for writing package documentation could be improved
  • hard to incorporate ocamldoc and markdown when writing documentation

Workarounds / package documentation:

  • inspect source code
  • odig, sherlocode.com, opam grep
  • look at package鈥檚 tests
  • search in forums, StackOverflow, look for links to package author鈥檚 documentation site in package鈥檚 public git repository

Pain points / learning section:

  • Layout/scroll problems on https://ocaml.org/doc. People need to scroll too much to see the content. Scrolling down the page does not show the tutorials and guides section, scrolling down the navbar on the left it is hard to scroll down to 鈥渃ommon error messages鈥, 鈥渂est practices鈥 and 鈥淥Caml platform鈥 (Too much scrolling required on the "Learn" page 路 Issue #850 路 ocaml/ocaml.org 路 GitHub)
  • Accessibility problems w/visual contrast (Add Accessibility-Checking to the Continuous Integration 路 Issue #835 路 ocaml/ocaml.org 路 GitHub)
  • Difficulty level/prerequisites of tutorials not always clear
  • Lack of important content (e.g. 鈥渟ingle-page syntax introduction鈥, dune and opam guide, task-oriented examples for different levels of language learning)
  • Styling difference between manual/stdlib API and main pages
  • 鈥淪tandard Library API鈥 link goes to the index instead of to Chapter 28 of the OCaml manual (manual gives a more adequate introduction to the standard library for beginners and does not expose internal functions like the automatically generated index does)
  • Problems with outdated information

Pain points overall:

  • Site doesn鈥檛 motivate people enough to use OCaml by showing how OCaml is cool, interesting, nice to use and how using it makes you a better programmer

Ideas/suggestions learning section:

  • The more basic sections, e.g. if statements, pointers, could be merged or made collapsible to make it easier to see all items on the side navigation
  • 鈥淧apers鈥 section is not so relevant to most OCaml beginners and should be moved below 鈥淏ooks鈥
  • Have a 鈥渂eginner鈥/鈥渁dvanced鈥 toggle at the top of the learn page that switches the content area to be tailored better to the different use cases
  • add more context on who should read a particular book (e.g. prerequisites, topics covered)

Workarounds learning section:

  • directly go to the manual
  • books, blogs, other sites
  • ask on forum/discord/StackOverflow
  • check ocamlverse

Tbh, this took a bit longer than I thought: there is so much useful info in your feedback! I want to add links to corresponding issues, but this will have to wait until I edit this post tomorrow.

10 Likes

Thanks! here is another suggestion:

when odoc builds documentation, the 鈥渢ype鈥 or 鈥渧al鈥 keywords are displayed strongly (boldface), whereas the information it provides, while being theoretically important, is of very little use in practice compared to the particular name of the value or of the type.
In fact, the name of the value/function/type should be much more prominent, in my opinion (this means also compared to the signature of the function). This is what most other languages docs do. I just made a comparison test for this:
compare:

  1. an 鈥渋mproved鈥 version of standard odoc output:
    Plt (oplot.Oplot.Plt)
    and
  2. the 鈥ocaml.org鈥 version:
    Oplot.Plt 路 oplot 0.71 路 OCaml Packages
3 Likes

Thank you, this is a great comparison! Here鈥檚 a quick patch minor improvements to package docs odoc styles by sabine 路 Pull Request #884 路 ocaml/ocaml.org 路 GitHub. After upgrading odoc on ocaml.org we can tweak a bit more.