- •Foreword
- •1. Introduction
- •2. Culture Shock
- •3. Preliminaries
- •Notation Used in This Book
- •Terminology
- •Sentences (statements)
- •Word Formation (tokenizing rules)
- •Numbers
- •Characters
- •Valence of Verbs (Binary and Unary Operators)
- •How Names (Identifiers) Get Assigned
- •Order of Evaluation
- •How Names Are Substituted
- •What a verb (function) looks like
- •Running a J program
- •The Execution Window; Script Windows
- •Names Defined at Startup
- •Step-By-Step Learning: Labs
- •J Documentation
- •Getting Help
- •4. A First Look At J Programs
- •Average Daily Balance
- •Calculating Chebyshev Coefficients
- •5. Declarations
- •Arrays
- •Cells
- •Phrases To Memorize
- •Constant Lists
- •Array-creating Verbs
- •6. Loopless Code I—Verbs Have Rank
- •Examples of Implicit Loops
- •The Concept of Verb Rank
- •Verb Execution—How Rank Is Used (Monads)
- •Controlling Verb Execution By Specifying a Rank
- •Examples Of Verb Rank
- •Negative Verb Rank
- •Verb Execution—How Rank Is Used (Dyads)
- •When Dyad Frames Differ: Operand Agreement
- •Order of Execution in Implied Loops
- •A Mistake To Avoid
- •7. Starting To Write In J
- •8. More Verbs
- •Arithmetic Dyads
- •Boolean Dyads
- •Min and Max Dyads
- •Arithmetic Monads
- •Boolean Monad
- •Operations on Arrays
- •9. Loopless Code II—Adverbs / and ~
- •Modifiers
- •The Adverb Monad u/
- •The adverb ~
- •10. Continuing to Write in J
- •11. Boxing (structures)
- •Terminology
- •Boxing As an Equivalent For Structures In C
- •12. Compound Verbs
- •Verb Sequences—u@:v and u@v
- •Making a Monad Into a Dyad: The Verbs [ and ]
- •Making a Dyad Into a Monad: u&n and m&v
- •13. Empty Operands
- •Execution On a Cell Of Fills
- •Empty cells
- •If Fill-Cells Are Not Enough
- •14. Loopless Code III—Adverbs \ and \.
- •15. Verbs for Arithmetic
- •Dyads
- •Monads (all rank 0)
- •16. Loopless Code IV
- •A Few J Tricks
- •Power/If/DoWhile Conjunction u^:n and u^:v
- •Tie and Agenda (switch)
- •17. More Verbs For Boxes
- •Dyad ; (Link) And Monad ; (Raze)
- •Dyad { Revisited: the Full Story
- •Split String Into J Words: Monad ;:
- •Fetch From Structure: Dyad {::
- •Report Boxing Level: Monad L.
- •18. Verb-Definition Revisited
- •What really happens during m :n and verb define
- •Compound Verbs Can Be Assigned
- •Dual-Valence verbs: u :v
- •The Suicide Verb [:
- •Multi-Line Comments Using 0 :0
- •Final Reminder
- •The Obverse u^:_1
- •Apply Under Transformation: u&.v and u&.:v
- •Defined obverses: u :.v
- •An observation about dyadic verbs
- •20. Performance: Measurement & Tips
- •Timing Individual Sentences
- •Compounds Recognized by the Interpreter
- •Use Large Verb-Ranks! and Integrated Rank Support
- •Shining a Light: The J Performance Monitor
- •21. Input And Output
- •Foreigns
- •File Operations 1!:n; Error Handling
- •Treating a File as a Noun: Mapped Files
- •Format Data For Printing: Monad And Dyad ":
- •Format an Array: 8!:n
- •Format binary data: 3!:n
- •printf, sprintf, and qprintf
- •Convert Character To Numeric: Dyad ".
- •22. Calling a DLL Under Windows
- •Memory Management
- •Aliasing of Variables
- •23. Socket Programming
- •Asynchronous Sockets and socket_handler
- •Names and IP Addresses
- •Connecting
- •Listening
- •Other Socket Verbs
- •24. Loopless Code V—Partitions
- •Find Unique Items: Monad ~. and Monad ~:
- •Apply On Subsets: Dyad u/.
- •Apply On Partitions: Monad u;.1 and u;.2
- •Apply On Specified Partitions: Dyad u;.1 and u;.2
- •Apply On Subarray: Dyad u;.0
- •Apply On All Subarrays: Dyad u;.3 and u;._3
- •Extracting Variable-Length Fields Using ^: and ;.1
- •Example: Combining Adjacent Boxes
- •25. When Programs Are Data
- •Calling a Published Name
- •Using the Argument To a Modifier
- •Invoking a Gerund: m`:6
- •Passing the Definition Of a Verb: 128!:2 (Apply)
- •Passing an Executable Sentence: Monad ". and 5!:5
- •26. Loopless Code VI
- •28. Modifying an array: m}
- •Monad I.—Indexes of the 1s in a Boolean Vector
- •29. Control Structures
- •while./do./end. and whilst./do./end.
- •if./do./else./end., if./do./elseif./do./end.
- •try./catch./catcht./end. and throw.
- •return.
- •assert.
- •30. Modular Code
- •Locales And Locatives
- •Assignment
- •Name Lookup
- •Changing The Current Locale
- •The Shared Locale 'z'
- •Using Locales
- •31. Writing Your Own Modifiers
- •Modifiers That Do Not Refer To x. Or y.
- •Modifiers That Refer To x. Or y.
- •32. Applied Mathematics in J
- •Complex Numbers
- •Matrix Operations
- •Calculus: d., D., D:, and p..
- •Taylor Series: t., t:, and T.
- •Hypergeometric Function with H.
- •Sparse Arrays: Monad and Dyad $.
- •Random Numbers: ?
- •Computational Addons
- •Useful Scripts Supplied With J
- •33. Elementary Mathematics in J
- •Verbs for Mathematics
- •Extended Integers, Rational Numbers, and x:
- •Factors and Primes: Monad p:, Monad and Dyad q:
- •Permutations: A. and C.
- •34. Graphics
- •Plot Package
- •2D Graphics: the gl2 Library
- •Displaying Tabular Data: the Grid Control
- •3D Graphics: OpenGL
- •35. Odds And Ends
- •Dyad # Revisited
- •Boxed words to string: Monad ;:^:_1
- •Spread: #^:_1
- •Choose From Lists Item-By-Item: monad m}
- •Recursion: $:
- •Make a Table: Adverb dyad u/
- •Cartesian Product: Monad {
- •Boolean Functions: Dyad m b.
- •Operations Inside Boxes: u L: n, u S: n
- •Comparison Tolerance !.f
- •Right Shift: Monad |.!.f
- •Generalized Transpose: Dyad |:
- •Monad i: and Dyad i:
- •Fast String Searching: s: (Symbols)
- •Fast Searching: m&i.
- •CRC Calculation
- •Unicode Characters: u:
- •Window Driver And Form Editor
- •Tacit Programming
- •36. Tacit Programs
- •37. First Look At Forks
- •38. Parsing and Execution I
- •39. Parsing and Execution II
- •The Parsing Table
- •Examples Of Parsing And Execution
- •Undefined Words
- •40. Forks, Hooks, and Compound Adverbs
- •Tacit and Compound Adverbs
- •Referring To a Noun In a Tacit Verb
- •41. Readable Tacit Definitions
- •Flatten a Verb: Adverb f.
- •Special Verb-Forms Used in Tacit Definitions
- •43. Common Mistakes
- •Mechanics
- •Programming Errors
- •44. Valedictory
- •45. Glossary
- •46. Error Messages
- •47. Index
Ts '(<a:;1) { a' 0.00939758 525568
Ts '1 {"1 a' 0.00952329 525184
Integrated rank support in dyad { gives the two forms equal performance. Look what happens when we replace the { by a user-defined verb with the same function:
from =. {
Ts '(<a:;1) from a' 0.00953335 525760
Ts '1 from"1 a' 0.365966 525696
from lacks integrated rank support, even though it is defined to have the same function as {, and it suffers when it is applied to each 1-cell. This is a good reason for you to learn the J primitives and not replace them with mnemonic equivalents.
Shining a Light: The J Performance Monitor
A magnet makes it easy to pick up a needle, but it won't much help you find a needle in a haystack. Likewise, being able to time and tune individual sentences will not suffice to let you improve the performance of a large J program. A large program spends most of its time executing a small subset of its code, and any improvements you make to other areas are simply wasted effort. I remember a case where a 20,000-line assemblerlanguage program was spending 30% of its time executing a single machine instruction— and that instruction turned out to be unnecessary! What you need is a tool that will direct your attention to the areas where a speedup will really matter.
The J Performance Monitor will show you how much time is spent executing each line of your application. You can run the Lab on the Performance Monitor to see all the facilities available, or you can jump right into timing your code with the simple sequence
load 'jpm'
Do this once to load the tool. Then, for each timing run, execute start_jpm_ 1e7
357142
The operand of start_jpm_ is the size in bytes of the trace buffer, and the result is the number of trace entries that can fit in the buffer. A trace entry is added for each line executed, and for entry and exit of explicit definitions (i. e. verbs defined with
verb define).
run the code you want to time viewtotal_jpm_ "
J will display a popup window with information about the time spent in each verb. An example display is
122
+--------- |
+------ |
+-------- |
+-------- |
+ |
-----+---- |
+--- |
+ |
|name |
|locale|all |
|here |
|here%|cum%|rep| |
||||
+--------- |
+------ |
+-------- |
+-------- |
+----- |
+---- |
+--- |
+ |
|accpay |
|base |
|0.001435|0.000829| 57.8| 58 |
|1 |
| |
|||
|intrep |
|base |
|0.000213|0.000213| 14.8| 73 |
|1 |
| |
|||
|accint |
|base |
|0.000393|0.000147| 10.2| 83 |
|1 |
| |
|||
|stretch |
|base |
|0.000142|0.000142| |
9.9| 93 |
|1 |
| |
||
|intexpand|base |
|0.000105|0.000105| |
7.3|100 |
|1 |
| |
|||
|[total] |
| |
| |
|0.001435|100.0|100 |
| |
| |
||
+--------- |
+------ |
+-------- |
+-------- |
+----- |
+---- |
+--- |
+ |
The columns contain the following information: name the name of the verb
locale the locale the verb was running in (we will discuss locales in a later chapter)
all the amount of time spent in this verb including time spent in verbs called by this verb
here the amount of time spent in this verb but not including time spent in verbs called by this verb
here% the here time as a percentage of total time cum% cumulative total of here%
rep the number of times the verb was executed
You should focus your attention on the here column. If you see a verb that is taking
longer than you think it should, double-click on its name to look at the details of its |
|
|||
execution. Double-clicking on accpay will pop up another window showing |
+ |
|||
+-------- |
+-------- |
+--- |
+---------------------------------- |
|
|all |
|here |
|rep|accpay |
| |
|
+-------- |
+-------- |
+--- |
+---------------------------------- |
+ |
|0.000041|0.000041|1 |
|monad |
| |
||
|0.000040|0.000040|1 |
|[8] if. 4~:#y. do. |
| |
||
|0.000000|0.000000|0 |
|[9] 'imm frq int pay' return. end.| |
|||
|0.000054|0.000054|1 |
|[10] 'm f i p'=.y. |
| |
||
|0.000116|0.000116|1 |
|[11] len=.$p=.f#p%f |
| |
||
|0.000724|0.000131|1 |
|[12] j=.}.len accint f intrep i |
| |
||
|0.000322|0.000322|1 |
|[13] r=.j*+/\p%m}.1,(m-1)}.j |
| |
||
|0.000137|0.000137|1 |
|[14] (len$(-f){.1)#r |
| |
||
|0.001435|0.000841|1 |
|total monad |
| |
||
+-------- |
+-------- |
+--- |
+---------------------------------- |
+ |
We see that line 13 takes the most time. Clicking on the column heading will sort the lines using that column as a key, making it easy for you to concentrate on the individual lines that are taking the most time.
You should be aware of one quirk. The Performance Monitor will account for the time spent in every line of a named verb that is explicitly defined (i. e. defined using verb define or 3 : or 4 :). Other verbs are accounted for only as a whole, not line-by-line. You may be surprised to find that a verb defined by
123
opaqueverb =: verb define"0 <definition here>
)
will not be treated line-by-line. Yes, there is an explicit definition, but opaqueverb is not that definition: opaqueverb is a compound produced by the rank conjunction " . If you want to look inside opaqueverb, you need to define it like so:
opaqueverb =: limpidverb"0 limpidverb =: verb define <definition here>
)
The J Performance Monitor makes it easy to give your code a good finish by pounding down the nails that are sticking up. As of J5.01a there are a few quirks you need to work around: you cannot have a verb with the same name as a locale; you must close a detail window before you create a new one; and time spent in explicit modifiers is not correctly accounted for.
124