~zainab/blog

d9e5070ed32c1d81f97cf573113a677eae6dd437 — zainab-ali 6 months ago 8dffdeb master
Add question aside
A src/assets/question.svg => src/assets/question.svg +1 -0
@@ 0,0 1,1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"/></svg>
\ No newline at end of file

M src/chapter-page.css.pp => src/chapter-page.css.pp +17 -0
@@ 515,6 515,16 @@ body.chapter-page main aside {
    padding: ◊|paragraph-spacing|px  ◊(* 2 paragraph-spacing)px;
}

body.chapter-page main aside.question {
    margin-bottom: ◊|(* 2 article-paragraph-spacing)|px;
}

body.chapter-page main aside.question header h1 {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

body.chapter-page main aside header h1 {
    font-variant: all-small-caps;
    font-size: ◊|body-font-size|px;


@@ 522,6 532,13 @@ body.chapter-page main aside header h1 {
    text-align: center;
}

body.chapter-page main div.answer {
    padding: 0 ◊(* 2 paragraph-spacing)px;
}
body.chapter-page main div.answer label {
    padding-left: ◊|paragraph-spacing|px;
}

body.chapter-page main div.highlight div.scala .k { color: ◊|dark-needle-colour| } /* Keyword */
body.chapter-page main div.highlight div.scala .s { color: #547054 } /* Strings */
body.chapter-page main div.highlight div.scala .c1 { color: ◊|dark-needle-colour| } /* Comments */

M src/chapters/2022-02-12-cats-effect-ioruntime/the-IORuntime.html.pm => src/chapters/2022-02-12-cats-effect-ioruntime/the-IORuntime.html.pm +20 -2
@@ 117,7 117,17 @@ pool, we must use a different constructor: the aptly named ◊code-inline{IO.blo
◊snippet[#:name "better-snooze"]{}

◊p{Let’s run a few better snoozes using our
◊code-inline{boundedRuntime}. How long should they take?}
◊code-inline{boundedRuntime}.}

◊question-block{
◊question{It took ◊|snooze-time| seconds to run ◊code-inline{snooze} and ◊|snooze-time-double|
seconds to run ◊code-inline{tenSnoozes} on a
◊code-inline{boundedRuntime}. How long should it take to run
◊code-inline{tenBetterSnoozes}?}

◊answer{◊|(string-titlecase snooze-time-double)| seconds.}
◊answer{◊|(string-titlecase snooze-time)| seconds.}
}

◊snippet[#:name "better-snooze-run"]{}



@@ 136,9 146,17 @@ compute-intensive ones?}

◊snippet[#:name "combined-blocking"]{}

◊p{The previous ◊code-inline{snoozeAndCompute} task took six


◊question-block{
◊question{The previous ◊code-inline{snoozeAndCompute} task took six
seconds. How long should this one take?}

◊answer{Six seconds.}
◊answer{Less than six seconds.}
}


◊snippet[#:name "combined-blocking-run"]{}

◊p{It’s much faster: the threads in the bounded compute pool no longer

M src/chapters/2022-02-12-cats-effect-ioruntime/thread-pools.html.pm => src/chapters/2022-02-12-cats-effect-ioruntime/thread-pools.html.pm +56 -18
@@ 35,8 35,17 @@ running it using our handy ◊code-inline{time} function:}

◊p{The ◊code-inline{parSequence} function produces an ◊code-inline{IO}
that runs multiple tasks in
parallel. If each task takes ◊|snooze-time| seconds, how long should
◊code-inline{parallelSnoozes} take?}
parallel.}

◊question-block{
◊question{
If each task takes ◊|snooze-time| seconds, how long should
◊code-inline{parallelSnoozes} take?
}
◊answer{◊|(string-titlecase snooze-time-double)| seconds.}
◊answer{◊|(string-titlecase snooze-time)| seconds.}
◊answer{Between ◊|snooze-time| and ◊|snooze-time-double| seconds.}
}

◊snippet[#:name "snooze-parallel-run"]{}



@@ 88,9 97,13 @@ with ◊code-inline{parSequence}:}

◊snippet[#:name "factorial-io-parallelized"]{}

◊p{How long should ◊code-inline{factorials} take to run?}
◊question-block{
◊question{How long should ◊code-inline{tenFactorials} take to run?}
◊answer{Two seconds.}
◊answer{Longer than two seconds.}
}
◊p{It took two seconds to run ◊code-inline{factorial} once, so it
should also take two seconds to run in parallel, shouldn’t it?:}
should also take two seconds to run in parallel, shouldn’t it?}

◊snippet[#:name "factorial-io-parallelized-run"]{}



@@ 99,7 112,7 @@ bit. You might have also found that the code ◊em{didn’t} take two seconds
— it took longer.}

◊p{This is different to our ◊code-inline{snooze} task, which always took
◊|snooze-time| seconds regardless of whether we ran one, ten or a
◊|snooze-time| seconds regardless of whether we ran one, two or a
thousand in parallel.}

◊p{Why would that be?}


@@ 140,16 153,23 @@ by timing each task:}
◊p{This gives a string description for each of the
twenty tasks corresponding to how long the task took to run.}

◊p{Let’s run it to check the times:}
◊question-block{
◊question{It took two seconds to run ◊code-inline{factorial} once and three
seconds to run ◊code-inline{tenFactorials}. How long should each of the
twenty tasks in ◊code-inline{timedFactorials} take to run?}

◊answer{Two seconds.}
◊answer{Six seconds.}
◊answer{Anywhere between two and six seconds.}
◊answer{◊code-inline{0.3} seconds.}
}

◊snippet[#:name "factorial-io-parallelized-time-each-run"]{}

◊p{That’s strange! The ◊code-inline{factorials} task may have taken
six seconds in total, but shouldn’t each task have taken two seconds?}

◊p{Instead, we see times of anywhere between two and six.}
◊p{Strange! We see times of anywhere between two and six.}

◊p{This is because all tasks are fired off at the same time, but our
◊p{All tasks are fired off at the same time, but our
processors switch between them as they run. A processor might start
computing a task, but put it on hold in order to compute a different
one, switching back to it at a later time.


@@ 176,10 196,8 @@ many memory-intensive computations would give us
◊code-inline{OutOfMemoryError} exceptions.}
}

◊p{This is why it’s generally much more useful to limit the number of
tasks that can be run in parallel.}

◊p{We can do this using ◊keyword{thread pools}.}
◊p{It’s generally much more useful to limit the number of
tasks that can be run in parallel. We can do this using ◊keyword{thread pools}.}

◊headline-link{Bounded and unbounded thread pools}



@@ 198,10 216,21 @@ number of tasks in parallel.}

◊p{It’s much slower than before — only two tasks are run at once.}

◊p{How long does each task take to run? We can check with ◊code-inline{timedFactorials}:}

◊question-block{
◊question{It took two seconds to run ◊code-inline{factorial} once and twelve
seconds to run ◊code-inline{tenFactorials} on a bounded
thread pool with two threads. How long should each of the
twenty tasks in ◊code-inline{timedFactorials} take to run?}

◊answer{Two seconds.}
◊answer{Twenty-four seconds.}
◊answer{Anywhere between two and twenty-four seconds.}
}

◊snippet[#:name "factorial-time-bounded-threadpool"]{}


◊p{Unlike the previous unbounded thread pool, each task takes two
seconds ⸺ the tasks might be ◊em{scheduled} at once, but they’re fired
off over time, once a ◊keyword{thread} is free to compute them.}


@@ 257,9 286,18 @@ construct an ◊code-inline{IO} that runs ten tasks in parallel:}

◊snippet[#:name "snooze-10"]{}

◊p{Let’s try running this our bounded thread pool. Each task takes
◊|snooze-time| seconds. How long should the ◊code-inline{tenSnoozes}
task take?}
◊p{Let’s try running this our bounded thread pool.}

◊question-block{
◊question{
Each ◊code-inline{snooze} takes ◊|snooze-time| seconds.
How long should ◊code-inline{tenSnoozes} take on a bounded thread pool
with eight threads?
}
◊answer{◊|(string-titlecase snooze-time)| seconds.}
◊answer{◊|(string-titlecase snooze-time-double)| seconds.}
◊answer{Longer than ◊|snooze-time-double| seconds.}
}

◊snippet[#:name "snooze-10-run"]{}


M src/pollen.rkt => src/pollen.rkt +30 -1
@@ 23,7 23,8 @@
         external-link
         image
         diagram
         abstract)
         abstract
         question-block)

(module setup racket/base
  (require racket/runtime-path)


@@ 96,3 97,31 @@

(define (abstract . text)
  `(p ([class "abstract"]) ,@text))

(define (question-block . contents)
  (let* (
         [question (car (filter-map (λ (sexpr) (and (pair? sexpr)
                                                    (equal? (car sexpr) 'question)
                                                    (cdr sexpr)))
                                    contents))]
         [question-str (string-join (map (λ (x) (format "~a" x)) question) "-")]
         [answers (filter-map (λ (sexpr)
                                (and (pair? sexpr)
                                     (equal? (car sexpr) 'answer)
                                     (cdr sexpr)))
                              contents)]
         [indexed-answers (for/list ([answer answers]
                                     [idx (in-naturals)])
                            `(div ([class "answer"])
                              (input ([id ,(string-append question-str "-" (number->string idx))]
                                      [name ,question-str]
                                      [type "radio"]))
                              (label ([for ,(string-append question-str "-" (number->string idx))]) ,@answer)))])
    `(aside ([class "question"])
            (header (h1 (img ([alt ""]
                              [src "/assets/question.svg"]))
                        (span "question")
                        (img ([alt ""]
                              [src "/assets/question.svg"]))))
          (p ,@question)
          ,@indexed-answers)))