├── .gitignore ├── LICENSE ├── README.md ├── project.clj └── src ├── clj_bench ├── apply.clj ├── iter.clj ├── loop_it.clj ├── map_chunking.clj ├── misc.clj ├── sort_by.clj ├── spy_test.clj └── vec_reduce.clj └── spy └── core.clj /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea/ 3 | .nrepl-port 4 | target/ 5 | **.swp 6 | .lein-repl-history 7 | results.md 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Source code distributed under the Eclipse Public License - v 1.0: 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE 4 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF 5 | THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial code and 12 | documentation distributed under this Agreement, and 13 | 14 | b) in the case of each subsequent Contributor: 15 | 16 | i) changes to the Program, and 17 | 18 | ii) additions to the Program; 19 | 20 | where such changes and/or additions to the Program originate from and 21 | are distributed by that particular Contributor. A Contribution 22 | 'originates' from a Contributor if it was added to the Program by such 23 | Contributor itself or anyone acting on such Contributor's 24 | behalf. Contributions do not include additions to the Program which: 25 | (i) are separate modules of software distributed in conjunction with 26 | the Program under their own license agreement, and (ii) are not 27 | derivative works of the Program. 28 | 29 | "Contributor" means any person or entity that distributes the Program. 30 | 31 | "Licensed Patents" mean patent claims licensable by a Contributor 32 | which are necessarily infringed by the use or sale of its Contribution 33 | alone or when combined with the Program. 34 | 35 | "Program" means the Contributions distributed in accordance with this 36 | Agreement. 37 | 38 | "Recipient" means anyone who receives the Program under this 39 | Agreement, including all Contributors. 40 | 41 | 2. GRANT OF RIGHTS 42 | 43 | a) Subject to the terms of this Agreement, each Contributor hereby 44 | grants Recipient a non-exclusive, worldwide, royalty-free copyright 45 | license to reproduce, prepare derivative works of, publicly display, 46 | publicly perform, distribute and sublicense the Contribution of such 47 | Contributor, if any, and such derivative works, in source code and 48 | object code form. 49 | 50 | b) Subject to the terms of this Agreement, each Contributor hereby 51 | grants Recipient a non-exclusive, worldwide, royalty-free patent 52 | license under Licensed Patents to make, use, sell, offer to sell, 53 | import and otherwise transfer the Contribution of such Contributor, if 54 | any, in source code and object code form. This patent license shall 55 | apply to the combination of the Contribution and the Program if, at 56 | the time the Contribution is added by the Contributor, such addition 57 | of the Contribution causes such combination to be covered by the 58 | Licensed Patents. The patent license shall not apply to any other 59 | combinations which include the Contribution. No hardware per se is 60 | licensed hereunder. 61 | 62 | c) Recipient understands that although each Contributor grants the 63 | licenses to its Contributions set forth herein, no assurances are 64 | provided by any Contributor that the Program does not infringe the 65 | patent or other intellectual property rights of any other entity. Each 66 | Contributor disclaims any liability to Recipient for claims brought by 67 | any other entity based on infringement of intellectual property rights 68 | or otherwise. As a condition to exercising the rights and licenses 69 | granted hereunder, each Recipient hereby assumes sole responsibility 70 | to secure any other intellectual property rights needed, if any. For 71 | example, if a third party patent license is required to allow 72 | Recipient to distribute the Program, it is Recipient's responsibility 73 | to acquire that license before distributing the Program. 74 | 75 | d) Each Contributor represents that to its knowledge it has sufficient 76 | copyright rights in its Contribution, if any, to grant the copyright 77 | license set forth in this Agreement. 78 | 79 | 3. REQUIREMENTS 80 | 81 | A Contributor may choose to distribute the Program in object code form 82 | under its own license agreement, provided that: 83 | 84 | a) it complies with the terms and conditions of this Agreement; and 85 | 86 | b) its license agreement: 87 | 88 | i) effectively disclaims on behalf of all Contributors all warranties 89 | and conditions, express and implied, including warranties or 90 | conditions of title and non-infringement, and implied warranties or 91 | conditions of merchantability and fitness for a particular purpose; 92 | 93 | ii) effectively excludes on behalf of all Contributors all liability 94 | for damages, including direct, indirect, special, incidental and 95 | consequential damages, such as lost profits; 96 | 97 | iii) states that any provisions which differ from this Agreement are 98 | offered by that Contributor alone and not by any other party; and 99 | 100 | iv) states that source code for the Program is available from such 101 | Contributor, and informs licensees how to obtain it in a reasonable 102 | manner on or through a medium customarily used for software exchange. 103 | 104 | When the Program is made available in source code form: 105 | 106 | a) it must be made available under this Agreement; and 107 | 108 | b) a copy of this Agreement must be included with each copy of the Program. 109 | 110 | Contributors may not remove or alter any copyright notices contained 111 | within the Program. 112 | 113 | Each Contributor must identify itself as the originator of its 114 | Contribution, if any, in a manner that reasonably allows subsequent 115 | Recipients to identify the originator of the Contribution. 116 | 117 | 4. COMMERCIAL DISTRIBUTION 118 | 119 | Commercial distributors of software may accept certain 120 | responsibilities with respect to end users, business partners and the 121 | like. While this license is intended to facilitate the commercial use 122 | of the Program, the Contributor who includes the Program in a 123 | commercial product offering should do so in a manner which does not 124 | create potential liability for other Contributors. Therefore, if a 125 | Contributor includes the Program in a commercial product offering, 126 | such Contributor ("Commercial Contributor") hereby agrees to defend 127 | and indemnify every other Contributor ("Indemnified Contributor") 128 | against any losses, damages and costs (collectively "Losses") arising 129 | from claims, lawsuits and other legal actions brought by a third party 130 | against the Indemnified Contributor to the extent caused by the acts 131 | or omissions of such Commercial Contributor in connection with its 132 | distribution of the Program in a commercial product offering. The 133 | obligations in this section do not apply to any claims or Losses 134 | relating to any actual or alleged intellectual property 135 | infringement. In order to qualify, an Indemnified Contributor must: a) 136 | promptly notify the Commercial Contributor in writing of such claim, 137 | and b) allow the Commercial Contributor to control, and cooperate with 138 | the Commercial Contributor in, the defense and any related settlement 139 | negotiations. The Indemnified Contributor may participate in any such 140 | claim at its own expense. 141 | 142 | For example, a Contributor might include the Program in a commercial 143 | product offering, Product X. That Contributor is then a Commercial 144 | Contributor. If that Commercial Contributor then makes performance 145 | claims, or offers warranties related to Product X, those performance 146 | claims and warranties are such Commercial Contributor's responsibility 147 | alone. Under this section, the Commercial Contributor would have to 148 | defend claims against the other Contributors related to those 149 | performance claims and warranties, and if a court requires any other 150 | Contributor to pay any damages as a result, the Commercial Contributor 151 | must pay those damages. 152 | 153 | 5. NO WARRANTY 154 | 155 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS 156 | PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 157 | KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY 158 | WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY 159 | OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely 160 | responsible for determining the appropriateness of using and 161 | distributing the Program and assumes all risks associated with its 162 | exercise of rights under this Agreement , including but not limited to 163 | the risks and costs of program errors, compliance with applicable 164 | laws, damage to or loss of data, programs or equipment, and 165 | unavailability or interruption of operations. 166 | 167 | 6. DISCLAIMER OF LIABILITY 168 | 169 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR 170 | ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, 171 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING 172 | WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF 173 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 174 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR 175 | DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED 176 | HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 177 | 178 | 7. GENERAL 179 | 180 | If any provision of this Agreement is invalid or unenforceable under 181 | applicable law, it shall not affect the validity or enforceability of 182 | the remainder of the terms of this Agreement, and without further 183 | action by the parties hereto, such provision shall be reformed to the 184 | minimum extent necessary to make such provision valid and enforceable. 185 | 186 | If Recipient institutes patent litigation against any entity 187 | (including a cross-claim or counterclaim in a lawsuit) alleging that 188 | the Program itself (excluding combinations of the Program with other 189 | software or hardware) infringes such Recipient's patent(s), then such 190 | Recipient's rights granted under Section 2(b) shall terminate as of 191 | the date such litigation is filed. 192 | 193 | All Recipient's rights under this Agreement shall terminate if it 194 | fails to comply with any of the material terms or conditions of this 195 | Agreement and does not cure such failure in a reasonable period of 196 | time after becoming aware of such noncompliance. If all Recipient's 197 | rights under this Agreement terminate, Recipient agrees to cease use 198 | and distribution of the Program as soon as reasonably 199 | practicable. However, Recipient's obligations under this Agreement and 200 | any licenses granted by Recipient relating to the Program shall 201 | continue and survive. 202 | 203 | Everyone is permitted to copy and distribute copies of this Agreement, 204 | but in order to avoid inconsistency the Agreement is copyrighted and 205 | may only be modified in the following manner. The Agreement Steward 206 | reserves the right to publish new versions (including revisions) of 207 | this Agreement from time to time. No one other than the Agreement 208 | Steward has the right to modify this Agreement. The Eclipse Foundation 209 | is the initial Agreement Steward. The Eclipse Foundation may assign 210 | the responsibility to serve as the Agreement Steward to a suitable 211 | separate entity. Each new version of the Agreement will be given a 212 | distinguishing version number. The Program (including Contributions) 213 | may always be distributed subject to the version of the Agreement 214 | under which it was received. In addition, after a new version of the 215 | Agreement is published, Contributor may elect to distribute the 216 | Program (including its Contributions) under the new version. Except as 217 | expressly stated in Sections 2(a) and 2(b) above, Recipient receives 218 | no rights or licenses to the intellectual property of any Contributor 219 | under this Agreement, whether expressly, by implication, estoppel or 220 | otherwise. All rights in the Program not expressly granted under this 221 | Agreement are reserved. 222 | 223 | This Agreement is governed by the laws of the State of New York and 224 | the intellectual property laws of the United States of America. No 225 | party to this Agreement will bring a legal action under this Agreement 226 | more than one year after the cause of action arose. Each party waives 227 | its rights to a jury trial in any resulting litigation. 228 | 229 | 230 | 231 | Images distributed under the Creative Commons Attribution + ShareAlike 232 | License version 3.0: 233 | 234 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS 235 | CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS 236 | PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE 237 | WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS 238 | PROHIBITED. 239 | 240 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND 241 | AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS 242 | LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU 243 | THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH 244 | TERMS AND CONDITIONS. 245 | 246 | 1. Definitions 247 | 248 | "Adaptation" means a work based upon the Work, or upon the Work 249 | and other pre-existing works, such as a translation, adaptation, 250 | derivative work, arrangement of music or other alterations of a 251 | literary or artistic work, or phonogram or performance and 252 | includes cinematographic adaptations or any other form in which 253 | the Work may be recast, transformed, or adapted including in any 254 | form recognizably derived from the original, except that a work 255 | that constitutes a Collection will not be considered an Adaptation 256 | for the purpose of this License. For the avoidance of doubt, where 257 | the Work is a musical work, performance or phonogram, the 258 | synchronization of the Work in timed-relation with a moving image 259 | ("synching") will be considered an Adaptation for the purpose of 260 | this License. 261 | 262 | "Collection" means a collection of literary or artistic works, 263 | such as encyclopedias and anthologies, or performances, phonograms 264 | or broadcasts, or other works or subject matter other than works 265 | listed in Section 1(f) below, which, by reason of the selection 266 | and arrangement of their contents, constitute intellectual 267 | creations, in which the Work is included in its entirety in 268 | unmodified form along with one or more other contributions, each 269 | constituting separate and independent works in themselves, which 270 | together are assembled into a collective whole. A work that 271 | constitutes a Collection will not be considered an Adaptation (as 272 | defined below) for the purposes of this License. 273 | 274 | "Creative Commons Compatible License" means a license that is 275 | listed at http://creativecommons.org/compatiblelicenses that has 276 | been approved by Creative Commons as being essentially equivalent 277 | to this License, including, at a minimum, because that license: 278 | (i) contains terms that have the same purpose, meaning and effect 279 | as the License Elements of this License; and, (ii) explicitly 280 | permits the relicensing of adaptations of works made available 281 | under that license under this License or a Creative Commons 282 | jurisdiction license with the same License Elements as this 283 | License. 284 | 285 | "Distribute" means to make available to the public the original 286 | and copies of the Work or Adaptation, as appropriate, through sale 287 | or other transfer of ownership. 288 | 289 | "License Elements" means the following high-level license 290 | attributes as selected by Licensor and indicated in the title of 291 | this License: Attribution, ShareAlike. 292 | 293 | "Licensor" means the individual, individuals, entity or entities 294 | that offer(s) the Work under the terms of this License. 295 | 296 | "Original Author" means, in the case of a literary or artistic 297 | work, the individual, individuals, entity or entities who created 298 | the Work or if no individual or entity can be identified, the 299 | publisher; and in addition (i) in the case of a performance the 300 | actors, singers, musicians, dancers, and other persons who act, 301 | sing, deliver, declaim, play in, interpret or otherwise perform 302 | literary or artistic works or expressions of folklore; (ii) in the 303 | case of a phonogram the producer being the person or legal entity 304 | who first fixes the sounds of a performance or other sounds; and, 305 | (iii) in the case of broadcasts, the organization that transmits 306 | the broadcast. 307 | 308 | "Work" means the literary and/or artistic work offered under the 309 | terms of this License including without limitation any production 310 | in the literary, scientific and artistic domain, whatever may be 311 | the mode or form of its expression including digital form, such as 312 | a book, pamphlet and other writing; a lecture, address, sermon or 313 | other work of the same nature; a dramatic or dramatico-musical 314 | work; a choreographic work or entertainment in dumb show; a 315 | musical composition with or without words; a cinematographic work 316 | to which are assimilated works expressed by a process analogous to 317 | cinematography; a work of drawing, painting, architecture, 318 | sculpture, engraving or lithography; a photographic work to which 319 | are assimilated works expressed by a process analogous to 320 | photography; a work of applied art; an illustration, map, plan, 321 | sketch or three-dimensional work relative to geography, 322 | topography, architecture or science; a performance; a broadcast; a 323 | phonogram; a compilation of data to the extent it is protected as 324 | a copyrightable work; or a work performed by a variety or circus 325 | performer to the extent it is not otherwise considered a literary 326 | or artistic work. 327 | 328 | "You" means an individual or entity exercising rights under this 329 | License who has not previously violated the terms of this License 330 | with respect to the Work, or who has received express permission 331 | from the Licensor to exercise rights under this License despite a 332 | previous violation. 333 | 334 | "Publicly Perform" means to perform public recitations of the Work 335 | and to communicate to the public those public recitations, by any 336 | means or process, including by wire or wireless means or public 337 | digital performances; to make available to the public Works in 338 | such a way that members of the public may access these Works from 339 | a place and at a place individually chosen by them; to perform the 340 | Work to the public by any means or process and the communication 341 | to the public of the performances of the Work, including by public 342 | digital performance; to broadcast and rebroadcast the Work by any 343 | means including signs, sounds or images. 344 | 345 | "Reproduce" means to make copies of the Work by any means 346 | including without limitation by sound or visual recordings and the 347 | right of fixation and reproducing fixations of the Work, including 348 | storage of a protected performance or phonogram in digital form or 349 | other electronic medium. 350 | 351 | 2. Fair Dealing Rights. Nothing in this License is intended to reduce, 352 | limit, or restrict any uses free from copyright or rights arising from 353 | limitations or exceptions that are provided for in connection with the 354 | copyright protection under copyright law or other applicable laws. 355 | 356 | 3. License Grant. Subject to the terms and conditions of this License, 357 | Licensor hereby grants You a worldwide, royalty-free, non-exclusive, 358 | perpetual (for the duration of the applicable copyright) license to 359 | exercise the rights in the Work as stated below: 360 | 361 | to Reproduce the Work, to incorporate the Work into one or more 362 | Collections, and to Reproduce the Work as incorporated in the 363 | Collections; 364 | 365 | to create and Reproduce Adaptations provided that any such 366 | Adaptation, including any translation in any medium, takes 367 | reasonable steps to clearly label, demarcate or otherwise identify 368 | that changes were made to the original Work. For example, a 369 | translation could be marked "The original work was translated from 370 | English to Spanish," or a modification could indicate "The 371 | original work has been modified."; 372 | 373 | to Distribute and Publicly Perform the Work including as 374 | incorporated in Collections; and, 375 | 376 | to Distribute and Publicly Perform Adaptations. 377 | 378 | For the avoidance of doubt: 379 | 380 | Non-waivable Compulsory License Schemes. In those 381 | jurisdictions in which the right to collect royalties through 382 | any statutory or compulsory licensing scheme cannot be waived, 383 | the Licensor reserves the exclusive right to collect such 384 | royalties for any exercise by You of the rights granted under 385 | this License; 386 | 387 | Waivable Compulsory License Schemes. In those jurisdictions in 388 | which the right to collect royalties through any statutory or 389 | compulsory licensing scheme can be waived, the Licensor waives 390 | the exclusive right to collect such royalties for any exercise 391 | by You of the rights granted under this License; and, 392 | 393 | Voluntary License Schemes. The Licensor waives the right to 394 | collect royalties, whether individually or, in the event that 395 | the Licensor is a member of a collecting society that 396 | administers voluntary licensing schemes, via that society, 397 | from any exercise by You of the rights granted under this 398 | License. 399 | 400 | The above rights may be exercised in all media and formats whether now 401 | known or hereafter devised. The above rights include the right to make 402 | such modifications as are technically necessary to exercise the rights 403 | in other media and formats. Subject to Section 8(f), all rights not 404 | expressly granted by Licensor are hereby reserved. 405 | 406 | 4. Restrictions. The license granted in Section 3 above is expressly 407 | made subject to and limited by the following restrictions: 408 | 409 | You may Distribute or Publicly Perform the Work only under the 410 | terms of this License. You must include a copy of, or the Uniform 411 | Resource Identifier (URI) for, this License with every copy of the 412 | Work You Distribute or Publicly Perform. You may not offer or 413 | impose any terms on the Work that restrict the terms of this 414 | License or the ability of the recipient of the Work to exercise 415 | the rights granted to that recipient under the terms of the 416 | License. You may not sublicense the Work. You must keep intact all 417 | notices that refer to this License and to the disclaimer of 418 | warranties with every copy of the Work You Distribute or Publicly 419 | Perform. When You Distribute or Publicly Perform the Work, You may 420 | not impose any effective technological measures on the Work that 421 | restrict the ability of a recipient of the Work from You to 422 | exercise the rights granted to that recipient under the terms of 423 | the License. This Section 4(a) applies to the Work as incorporated 424 | in a Collection, but this does not require the Collection apart 425 | from the Work itself to be made subject to the terms of this 426 | License. If You create a Collection, upon notice from any Licensor 427 | You must, to the extent practicable, remove from the Collection 428 | any credit as required by Section 4(c), as requested. If You 429 | create an Adaptation, upon notice from any Licensor You must, to 430 | the extent practicable, remove from the Adaptation any credit as 431 | required by Section 4(c), as requested. 432 | 433 | You may Distribute or Publicly Perform an Adaptation only under 434 | the terms of: (i) this License; (ii) a later version of this 435 | License with the same License Elements as this License; (iii) a 436 | Creative Commons jurisdiction license (either this or a later 437 | license version) that contains the same License Elements as this 438 | License (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative 439 | Commons Compatible License. If you license the Adaptation under 440 | one of the licenses mentioned in (iv), you must comply with the 441 | terms of that license. If you license the Adaptation under the 442 | terms of any of the licenses mentioned in (i), (ii) or (iii) (the 443 | "Applicable License"), you must comply with the terms of the 444 | Applicable License generally and the following provisions: (I) You 445 | must include a copy of, or the URI for, the Applicable License 446 | with every copy of each Adaptation You Distribute or Publicly 447 | Perform; (II) You may not offer or impose any terms on the 448 | Adaptation that restrict the terms of the Applicable License or 449 | the ability of the recipient of the Adaptation to exercise the 450 | rights granted to that recipient under the terms of the Applicable 451 | License; (III) You must keep intact all notices that refer to the 452 | Applicable License and to the disclaimer of warranties with every 453 | copy of the Work as included in the Adaptation You Distribute or 454 | Publicly Perform; (IV) when You Distribute or Publicly Perform the 455 | Adaptation, You may not impose any effective technological 456 | measures on the Adaptation that restrict the ability of a 457 | recipient of the Adaptation from You to exercise the rights 458 | granted to that recipient under the terms of the Applicable 459 | License. This Section 4(b) applies to the Adaptation as 460 | incorporated in a Collection, but this does not require the 461 | Collection apart from the Adaptation itself to be made subject to 462 | the terms of the Applicable License. 463 | 464 | If You Distribute, or Publicly Perform the Work or any Adaptations 465 | or Collections, You must, unless a request has been made pursuant 466 | to Section 4(a), keep intact all copyright notices for the Work 467 | and provide, reasonable to the medium or means You are utilizing: 468 | (i) the name of the Original Author (or pseudonym, if applicable) 469 | if supplied, and/or if the Original Author and/or Licensor 470 | designate another party or parties (e.g., a sponsor institute, 471 | publishing entity, journal) for attribution ("Attribution 472 | Parties") in Licensor's copyright notice, terms of service or by 473 | other reasonable means, the name of such party or parties; (ii) 474 | the title of the Work if supplied; (iii) to the extent reasonably 475 | practicable, the URI, if any, that Licensor specifies to be 476 | associated with the Work, unless such URI does not refer to the 477 | copyright notice or licensing information for the Work; and (iv) , 478 | consistent with Ssection 3(b), in the case of an Adaptation, a 479 | credit identifying the use of the Work in the Adaptation (e.g., 480 | "French translation of the Work by Original Author," or 481 | "Screenplay based on original Work by Original Author"). The 482 | credit required by this Section 4(c) may be implemented in any 483 | reasonable manner; provided, however, that in the case of a 484 | Adaptation or Collection, at a minimum such credit will appear, if 485 | a credit for all contributing authors of the Adaptation or 486 | Collection appears, then as part of these credits and in a manner 487 | at least as prominent as the credits for the other contributing 488 | authors. For the avoidance of doubt, You may only use the credit 489 | required by this Section for the purpose of attribution in the 490 | manner set out above and, by exercising Your rights under this 491 | License, You may not implicitly or explicitly assert or imply any 492 | connection with, sponsorship or endorsement by the Original 493 | Author, Licensor and/or Attribution Parties, as appropriate, of 494 | You or Your use of the Work, without the separate, express prior 495 | written permission of the Original Author, Licensor and/or 496 | Attribution Parties. 497 | 498 | Except as otherwise agreed in writing by the Licensor or as may be 499 | otherwise permitted by applicable law, if You Reproduce, 500 | Distribute or Publicly Perform the Work either by itself or as 501 | part of any Adaptations or Collections, You must not distort, 502 | mutilate, modify or take other derogatory action in relation to 503 | the Work which would be prejudicial to the Original Author's honor 504 | or reputation. Licensor agrees that in those jurisdictions 505 | (e.g. Japan), in which any exercise of the right granted in 506 | Section 3(b) of this License (the right to make Adaptations) would 507 | be deemed to be a distortion, mutilation, modification or other 508 | derogatory action prejudicial to the Original Author's honor and 509 | reputation, the Licensor will waive or not assert, as appropriate, 510 | this Section, to the fullest extent permitted by the applicable 511 | national law, to enable You to reasonably exercise Your right 512 | under Section 3(b) of this License (right to make Adaptations) but 513 | not otherwise. 514 | 515 | 5. Representations, Warranties and Disclaimer 516 | 517 | UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, 518 | LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR 519 | WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, 520 | STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF 521 | TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, 522 | NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, 523 | OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT 524 | DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED 525 | WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 526 | 527 | 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY 528 | APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY 529 | LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR 530 | EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, 531 | EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 532 | 533 | 7. Termination 534 | 535 | This License and the rights granted hereunder will terminate 536 | automatically upon any breach by You of the terms of this 537 | License. Individuals or entities who have received Adaptations or 538 | Collections from You under this License, however, will not have 539 | their licenses terminated provided such individuals or entities 540 | remain in full compliance with those licenses. Sections 1, 2, 5, 541 | 6, 7, and 8 will survive any termination of this License. 542 | 543 | Subject to the above terms and conditions, the license granted 544 | here is perpetual (for the duration of the applicable copyright in 545 | the Work). Notwithstanding the above, Licensor reserves the right 546 | to release the Work under different license terms or to stop 547 | distributing the Work at any time; provided, however that any such 548 | election will not serve to withdraw this License (or any other 549 | license that has been, or is required to be, granted under the 550 | terms of this License), and this License will continue in full 551 | force and effect unless terminated as stated above. 552 | 553 | 8. Miscellaneous 554 | 555 | Each time You Distribute or Publicly Perform the Work or a 556 | Collection, the Licensor offers to the recipient a license to the 557 | Work on the same terms and conditions as the license granted to 558 | You under this License. 559 | 560 | Each time You Distribute or Publicly Perform an Adaptation, 561 | Licensor offers to the recipient a license to the original Work on 562 | the same terms and conditions as the license granted to You under 563 | this License. 564 | 565 | If any provision of this License is invalid or unenforceable under 566 | applicable law, it shall not affect the validity or enforceability 567 | of the remainder of the terms of this License, and without further 568 | action by the parties to this agreement, such provision shall be 569 | reformed to the minimum extent necessary to make such provision 570 | valid and enforceable. 571 | 572 | No term or provision of this License shall be deemed waived and no 573 | breach consented to unless such waiver or consent shall be in 574 | writing and signed by the party to be charged with such waiver or 575 | consent. 576 | 577 | This License constitutes the entire agreement between the parties 578 | with respect to the Work licensed here. There are no 579 | understandings, agreements or representations with respect to the 580 | Work not specified here. Licensor shall not be bound by any 581 | additional provisions that may appear in any communication from 582 | You. This License may not be modified without the mutual written 583 | agreement of the Licensor and You. 584 | 585 | The rights granted under, and the subject matter referenced, in 586 | this License were drafted utilizing the terminology of the Berne 587 | Convention for the Protection of Literary and Artistic Works (as 588 | amended on September 28, 1979), the Rome Convention of 1961, the 589 | WIPO Copyright Treaty of 1996, the WIPO Performances and 590 | Phonograms Treaty of 1996 and the Universal Copyright Convention 591 | (as revised on July 24, 1971). These rights and subject matter 592 | take effect in the relevant jurisdiction in which the License 593 | terms are sought to be enforced according to the corresponding 594 | provisions of the implementation of those treaty provisions in the 595 | applicable national law. If the standard suite of rights granted 596 | under applicable copyright law includes additional rights not 597 | granted under this License, such additional rights are deemed to 598 | be included in the License; this License is not intended to 599 | restrict the license of any rights under applicable law. 600 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # See: 2 | 3 | https://medium.com/@rauh/faster-clojure-reduce-57a104448ea4 4 | 5 | # License 6 | 7 | Distributed under the Eclipse Public License, the same as Clojure uses. 8 | 9 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject bench "0.1.0-SNAPSHOT" 2 | :dependencies [ 3 | ;[org.clojure/clojure "1.10.0-master-SNAPSHOT"] 4 | [org.clojure/clojure "1.9.0"] 5 | [criterium "0.4.4"] 6 | [com.squareup/javapoet "1.9.0"] 7 | [proteus "0.1.6"]] 8 | ;:main ^:skip-aot clj-bench.core 9 | :global-vars {*warn-on-reflection* true 10 | ;*assert* false 11 | } 12 | :target-path "target/%s" 13 | :jvm-opts ["-server" 14 | "-Xms4g" 15 | "-Xmx4g" 16 | ;"-Dclojure.spec.check-asserts=false" 17 | ;"-Dclojure.spec.compile-asserts=false" 18 | ;"-XX:+PrintCompilation" 19 | ;"-XX:+UnlockDiagnosticVMOptions" ;;req for printinlining 20 | ;"-XX:+PrintInlining" 21 | "-Dclojure.compiler.direct-linking=true"] 22 | :profiles {:uberjar {:aot :all}}) 23 | -------------------------------------------------------------------------------- /src/clj_bench/apply.clj: -------------------------------------------------------------------------------- 1 | (ns clj-bench.apply 2 | (:require 3 | [criterium.core :as crit] 4 | [clojure.reflect :as reflect] 5 | [clojure.set :as set]) 6 | (:import 7 | (com.squareup.javapoet MethodSpec TypeName ArrayTypeName MethodSpec$Builder 8 | ParameterSpec ClassName JavaFile TypeSpec CodeBlock) 9 | (javax.lang.model.element Modifier) 10 | (java.util Arrays) 11 | (clojure.lang RestFn AFn ArrayChunk ChunkedCons) 12 | (java.lang.reflect Type) 13 | (javax.lang.model.type TypeMirror) 14 | (java.util.function ObjDoubleConsumer))) 15 | 16 | (set! *warn-on-reflection* false) 17 | 18 | (defn array [& items] (into-array items)) 19 | 20 | (defn modifiers 21 | [& mods] 22 | (into-array Modifier 23 | (map #(Modifier/valueOf (.toUpperCase ^String (name %))) mods))) 24 | 25 | (defn add-modifier 26 | [x & mods] 27 | (.addModifiers x (apply modifiers mods))) 28 | 29 | (defn method 30 | ([name] 31 | (method name #{})) 32 | ([name modifiers] 33 | (let [meth (MethodSpec/methodBuilder name)] 34 | (apply add-modifier meth modifiers) 35 | meth))) 36 | 37 | (defn array-type 38 | [x] 39 | (ArrayTypeName/of x)) 40 | 41 | (defn clsname 42 | ([simple-name] 43 | (if (string? simple-name) 44 | (clsname "" simple-name) 45 | simple-name)) 46 | ([pckg simple-name & args] 47 | ;(ClassName/bestGuess "Fooo") 48 | (ClassName/get pckg simple-name (into-array String args)))) 49 | 50 | (defn returns 51 | [x t] 52 | (.returns x (clsname t))) 53 | 54 | (defn bclass 55 | [class-name super] 56 | (let [cb (TypeSpec/classBuilder class-name)] 57 | (when super (.superclass cb (clsname super))) 58 | cb)) 59 | 60 | (defn add-method 61 | [x m] 62 | (.addMethod x m)) 63 | 64 | (defn code! 65 | [x] 66 | (str (.build x))) 67 | 68 | ;(defprotocol ) ;; Use protocols? 69 | (defn add-param 70 | [x type name] 71 | (.addParameter x (clsname type) name (modifiers))) 72 | 73 | (defn statement 74 | ([_]) 75 | ([x s & args] 76 | (.addStatement x s (into-array Object args)))) 77 | 78 | (defn add-code 79 | "Adds a CodeBlock to the method" 80 | ([x cb] 81 | (.addCode x cb)) 82 | ([x cb & args] 83 | (.addCode x cb (into-array args)))) 84 | 85 | (defn else 86 | ([_]) 87 | ([x s & args] 88 | (.nextControlFlow x s (into-array Object args)))) 89 | 90 | (defn package! 91 | "Outputs the a file inside clojure.lang package." 92 | [cls] 93 | (str (.build (JavaFile/builder "clojure.lang" cls)))) 94 | 95 | (defn do-invoke 96 | "Generates a doInvoke fn returning null." 97 | [num-pre] 98 | (let [meth 99 | (-> (method "doInvoke" #{:protected}) 100 | (returns "Object") 101 | (statement "return null"))] 102 | (dotimes [i num-pre] 103 | (add-param meth "Object" (str "arg" (inc i)))) 104 | (add-param meth "Object" "args"))) 105 | #_(code! (do-invoke 0)) ;; 0..20 106 | #_(code! (do-invoke 20)) ;; 0..20 107 | 108 | (defmacro IF 109 | [x s args & body] 110 | `(-> ~x 111 | (.beginControlFlow ~s (into-array Object ~args)) 112 | ~@body 113 | (.endControlFlow))) 114 | 115 | (defn ret1 116 | ([sym] 117 | (if (symbol? sym) 118 | (str sym) 119 | (str "Util.ret1(" sym ", " sym " = null)"))) 120 | ([expr sym] 121 | (str "Util.ret1(" expr ", " sym " = null)") )) 122 | 123 | ;; TODO: RT.seqToArray( 124 | (defn do-fn-invoke! 125 | "Generates a " 126 | [f ident [farg & args] & [arr-last?]] 127 | (let [cb (CodeBlock/builder)] 128 | (.add cb "$L(" (array f)) 129 | (.add cb (ret1 farg) (array)) 130 | (when (some? args) 131 | (.add cb "\n" (array)) 132 | (dotimes [_ ident] 133 | (.indent cb))) 134 | (doseq [arg (butlast args)] 135 | (.add cb (str ", " (ret1 arg) "\n") (array))) 136 | (when-some [lar (last args)] 137 | (.add cb (str ", " 138 | (if arr-last? 139 | (str "RT.seqToArray(" (ret1 lar) ")") 140 | (ret1 lar))) 141 | (array))) 142 | (when (some? args) 143 | (dotimes [_ ident] 144 | (.unindent cb))) 145 | (.build (.add cb ");\n" (array))))) 146 | 147 | (defn invoke! 148 | [sym ident args & [arr-last?]] 149 | (if (empty? args) 150 | (CodeBlock/of (str sym "();\n") (into-array [])) 151 | (do-fn-invoke! sym ident args arr-last?))) 152 | 153 | (defn arg [n] (str "a" n)) 154 | 155 | ;; AFn: Gen applyToHelper: 156 | (let [args "args" 157 | ifn "ifn" 158 | n 4 ;; Number of given static args 0..4 159 | m (-> (method (str (if (zero? n) "applyTo" "multiApplyTo") "Helper") 160 | #{:public :static}) 161 | (returns "Object"))] 162 | (add-param m "IFn" ifn) 163 | (dotimes [i n] 164 | (add-param m "Object" (arg (inc i)))) 165 | (add-param m "ISeq" args) 166 | (doseq [i (range n 21)] ;; 21 for applyTo 167 | (when (< n i) 168 | (-> m 169 | (statement "Object $L = $L.first()" (arg i) args) 170 | (statement "$L = $L.next()" args args))) 171 | (IF m "if($L == null)" [args] 172 | (add-code "return $L" (invoke! (str ifn ".invoke") 8 (map arg (range 1 (inc i))))))) 173 | (add-code m "return $L" (invoke! (str ifn ".invoke") 8 174 | (conj (mapv arg (range 1 21)) args) true)) 175 | (code! m)) 176 | 177 | (defn args-list* 178 | [ar args] 179 | (if (empty? ar) 180 | (ret1 args) 181 | (reduce 182 | (fn [s arg] 183 | (str "RT.cons(" (ret1 arg) ", " s ")")) 184 | (str "RT.cons(" (ret1 (last ar)) ", " (ret1 args) ")") 185 | (reverse (butlast ar))))) 186 | 187 | ;; RestFn: Code for multiApplyTo and applyTo (n==0) 188 | (let [mra "mra" 189 | n 1 ;; number of given args, eg. 2: [Object a1, Object a2, ISeq args] [0..4] 190 | args "args" 191 | m (-> (method (if (zero? n) "applyTo" "multiApplyTo") #{:public}) 192 | (returns "Object"))] 193 | (dotimes [i n] 194 | (add-param m "Object" (arg (inc i)))) 195 | (add-param m "ISeq" args) 196 | (statement m "int $L = getRequiredArity()" mra) 197 | ;; We still need to check mra < i or the code will walk the ENTIRE seq and then call 198 | ;; invoke() on it. (this would fail: (apply (fn [& x] x) 3 (range 22)) ) if not doing it. 199 | (doseq [i (range n)] 200 | (IF m "if($L == $L)" [mra i] 201 | (add-code 202 | "return $L" 203 | (invoke! "doInvoke" 7 (conj (mapv arg (range 1 (inc i))) 204 | (symbol (args-list* (mapv arg (range (inc i) (inc n))) 205 | args))))))) 206 | (doseq [i (range n 21)] ;; 21 207 | (when (< n i) 208 | (-> m 209 | (statement "Object $L = $L.first()" (arg i) args) 210 | (statement "$L = $L.next()" args args))) 211 | (IF m "if($L == null)" [args] 212 | (add-code "return $L" (invoke! "invoke" 6 (map arg (range 1 (inc i)))))) 213 | (IF m "if($L == $L)" [mra i] 214 | (add-code "return $L" (invoke! "doInvoke" 7 (conj (mapv arg (range 1 (inc i))) args))))) 215 | (statement m "return throwArity(-1)") 216 | (code! m)) 217 | 218 | ;;;;;;;;;;;;;;;;;;;; BENCH ;;;;;;;;;;;;;;;;;;;;;;; 219 | ;;;;;;;;;;;;;;;;;;;; BENCH ;;;;;;;;;;;;;;;;;;;;;;; 220 | (defn bench! 221 | [rfn fixed xs] 222 | (let [fixed (filter number? fixed) 223 | afn (fn 224 | ([] 1) 225 | ([x] x) 226 | ([x y] y) 227 | ([x y z] z) 228 | ([x y z, a] a) 229 | ([x y z, a b] b) 230 | ([x y z, a b c] c) 231 | ([x y z, a b c, d] d) 232 | ([x y z, a b c, d e] e) 233 | ([x y z, a b c, d e f] f) 234 | ([x y z, a b c, d e f, g] g) 235 | ([x y z, a b c, d e f, g h] h))] 236 | ;; Make apply also see types other than vecs: 237 | (apply apply (concat [afn] fixed [(into () xs)])) 238 | (prn "Args:" (count xs) " Fixed:" (count fixed) " -- " (clojure-version)) 239 | ;; Always run both, even benching just one: 240 | ;; Make apply also see AFn, not just RestFn for realistic workload 241 | (doseq [f [afn rfn]] 242 | (prn ">>>>" (bases (class f)) "<<<<<") 243 | (case (count fixed) 244 | 0 (crit/quick-bench (apply f xs)) 245 | 1 (let [[x1] fixed] 246 | (crit/quick-bench (apply f x1 xs))) 247 | 2 (let [[x1 x2] fixed] 248 | (crit/quick-bench (apply f x1 x2 xs))) 249 | 3 (let [[x1 x2 x3] fixed] 250 | (crit/quick-bench (apply f x1 x2 x3 xs))) 251 | 4 (let [[x1 x2 x3 x4] fixed] 252 | (crit/quick-bench (apply f x1 x2 x3 x4 xs))))))) 253 | (defn r-0 254 | ([] 1) 255 | ([& xs] 1)) 256 | 257 | (defn r-3 258 | ([] 1) 259 | ([x] x) 260 | ([x y] x) 261 | ([x y z] z) 262 | ([x y z & xs] z)) 263 | (defn r-6 264 | ([] 1) 265 | ([x] x) 266 | ([x y] x) 267 | ([a b c, d e f] f) 268 | ([a b c, d e f & xs] f)) 269 | 270 | (comment 271 | ;; Notation: 272 | ;; [old-time-ns, new-time-ns] <-- for AFn 273 | ;; #{old-time-ns, new-time-ns} <-- for RestFn 274 | ;; A string means the bench is redundant and was already done above 275 | 276 | ;;;;;;;;;;;;;;;;; FIXED args ;;;;;;;;;;;;;;;;;;;;;;;; 277 | ;; Testing RT.cons usage: (ie too many args given, MRA is very small (0)) 278 | ;; Giving nil: 279 | (bench! r-0 [1 - - -] nil) #{26 18} [27 15] 280 | (bench! r-0 [1 2 - -] nil) #{31 19} [46, 12] 281 | (bench! r-0 [1 2 3 -] nil) #{41 20} [128, 9] 282 | (bench! r-0 [1 2 3 4] nil) #{58 45} [152 33] 283 | ;; Providing one arg in addition: 284 | (bench! r-0 [1 - - -] [1]) #{79 26} [104 21] 285 | (bench! r-0 [1 2 - -] [1]) #{78 25} [173, 20] 286 | (bench! r-0 [1 2 3 -] [1]) #{84 25} [250, 17] 287 | (bench! r-0 [1 2 3 4] [1]) #{67 40} [183 31] 288 | ;; "Common" config, ie 3 args and then rest: 289 | (bench! r-3 [1 - - -] [1]) #{""} [""] 290 | (bench! r-3 [1 2 - -] [1]) #{237 21} [""] 291 | (bench! r-3 [1 2 3 -] [1]) #{172 19} [""] 292 | (bench! r-3 [1 2 3 4] [1]) #{148 44} [""] 293 | 294 | 295 | ;; 296 | (bench! r-6 [1 2 3] [4 5 6]) #{310 30} [209 38] 297 | 298 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 299 | ;; No fixed args 300 | (bench! r-0 [] [1]) #{28 21} [32 33] 301 | 302 | ) 303 | 304 | (comment 305 | ;; Real world perf: 306 | 307 | (let [xs {:a 2} 308 | upd-path [:a]] 309 | ;; 161ns , 130ns 310 | (crit/quick-bench (update-in xs upd-path inc))) 311 | 312 | (let [xs {:a []} 313 | upd-path [:a]] 314 | ;; 280ns, 212ns 315 | (crit/quick-bench (update-in xs upd-path conj 1))) 316 | 317 | (let [xs (vec (range 2))] 318 | ;; 450ns, 335ns 319 | (crit/quick-bench (mapcat vector xs))) 320 | 321 | 322 | (let [f (with-meta (fn [x y] (+ x y)) {0 1})] 323 | ;; 65ns, 45ns 324 | (crit/quick-bench (f 1 2))) 325 | 326 | ) 327 | 328 | 329 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 330 | (comment 331 | (let [f (fn ([] "") ([& s] [s]))] 332 | (list (apply f []) 333 | (f 1) 334 | (bean f))) 335 | 336 | (-> (bclass "RestFn" "AFunction") 337 | (add-modifier :public :abstract) 338 | (add-method (-> (method "getRequiredArity" #{:abstract :public}) 339 | (returns Integer/TYPE) 340 | (.build))) 341 | (code!)) 342 | 343 | (-> (method "main") 344 | (add-modifier :public :static) 345 | (returns Object) 346 | (.addParameter (array-type String) "args" (modifiers)) 347 | (code!))) 348 | -------------------------------------------------------------------------------- /src/clj_bench/iter.clj: -------------------------------------------------------------------------------- 1 | (ns clj-bench.iter 2 | (:require 3 | [clj-bench.loop-it :refer [loop-it multi-iter multi-iter-lazy]] 4 | [clj-bench.vec-reduce :refer [sv-loop]] 5 | [criterium.core :as crit :refer [quick-bench bench]] 6 | [proteus :refer :all] 7 | [clojure.walk :as walk] 8 | [clojure.core.reducers :as r] 9 | [clojure.string :as str] 10 | [clojure.java.io :as io]) 11 | (:import (java.util Iterator ArrayList Collection) 12 | (java.util.concurrent.atomic AtomicInteger) 13 | (clojure.lang IndexedSeq ArraySeq AFn))) 14 | 15 | (set! *warn-on-reflection* true) 16 | ;(set! *unchecked-math* :warn-on-boxed) 17 | 18 | (def xs (vec (range 1e6))) 19 | (def xs-large (vec (range 1e7))) 20 | 21 | (comment 22 | ;; check thread safety: 23 | (let [n (rand-int 10000) 24 | xs (seq (vec (range n))) 25 | arrlist (ArrayList. ^Collection xs)] 26 | (future 27 | (dotimes [_ 10000] 28 | (.set arrlist (rand-int n) (rand-int n)) 29 | (assoc xs (rand-int n) (rand-int n))) 30 | (prn "DONE")) 31 | (Thread/sleep 10) 32 | [(/ (* n (dec n)) 2) 33 | (loop-it [^long x xs :let [sum 0]] (recur (+ sum x)) sum) 34 | (loop-it [^long x arrlist :let [sum 0]] (recur (+ sum x)) sum)])) 35 | 36 | 37 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 38 | ;; Single reduce, primitve: 39 | (defn sum-reduce [xs] (reduce + 0 xs)) 40 | 41 | (defn sum-loop-prim 42 | [xs] 43 | (loop [xs (seq xs), sum 0] 44 | (if xs 45 | (recur (next xs) (+ sum ^long (first xs))) 46 | sum))) 47 | 48 | (defn sum-loop-iter 49 | [xs] 50 | (loop-it [x xs, :let [sum 0]] 51 | (recur (+ sum ^long x)) 52 | sum)) 53 | 54 | (defn sum-loop 55 | [xs] 56 | (loop [xs (seq xs) 57 | sum (Long. 0)] ;; Avoid primitive math. 58 | (if xs 59 | (recur (next xs) (+ sum (first xs))) 60 | sum))) 61 | #_(sum-loop xs-large) 62 | 63 | (comment 64 | (quick-bench (sum-reduce xs-large)) ;; 177ms 65 | (quick-bench (sum-loop xs-large)) ;; 178ms 66 | (quick-bench (sum-loop-prim xs-large)) ;; 130ms 67 | (quick-bench (sum-loop-iter xs-large)) ;; 59ms 68 | ()) 69 | 70 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 71 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 72 | ;; ODD/EVEN accumulator: 73 | (defn odd-even-reduce [xs] 74 | (reduce (fn [[odd even] x] 75 | (if (odd? x) 76 | [(inc odd) even] 77 | [odd (inc even)])) [0 0] xs)) 78 | (defn odd-even-reduce-count [xs] 79 | (reduce (fn [s x] (inc s)) 0 xs)) 80 | (defn odd-even-reduce-prim-array [xs] 81 | (reduce (fn [^longs arr x] 82 | (if (odd? x) 83 | (aset arr 0 (inc (aget arr 0))) 84 | (aset arr 0 (inc (aget arr 0)))) 85 | arr) 86 | (long-array [0 0]) xs)) 87 | (defn odd-even-reduce-volatile [xs] 88 | (let [even (volatile! 0) 89 | odd (volatile! 0)] 90 | (reduce (fn [_ x] 91 | (if (odd? x) 92 | (vswap! even inc) 93 | (vswap! odd inc))) 94 | nil xs) 95 | [@odd @even])) 96 | (defn odd-even-doseq [xs] 97 | (let [odd (volatile! 0) 98 | even (volatile! 0)] 99 | (doseq [x xs] 100 | (if (odd? x) 101 | (vswap! odd inc) 102 | (vswap! even inc))) 103 | [@odd @even])) 104 | (defn odd-even-iter 105 | [xs] 106 | (let [it (clojure.lang.RT/iter xs)] 107 | (loop [odd 0 108 | even 0] 109 | (if (.hasNext it) 110 | (if (odd? (.next it)) 111 | (recur (inc odd) even) 112 | (recur odd (inc even))) 113 | [odd even])))) 114 | (defn odd-even-loop-it 115 | [xs] 116 | (loop-it [x xs 117 | :let [odd 0, even 0]] 118 | (if (odd? x) 119 | (recur (inc odd) even) 120 | (recur odd (inc even))) 121 | [odd even])) 122 | #_(odd-even-loop-it xs-large) 123 | (defn odd-even-mutable [xs] 124 | (let-mutable [odd 0 125 | even 0] 126 | (doseq [x xs] 127 | (if (odd? x) 128 | (set! odd (inc odd)) 129 | (set! even (inc even)))) 130 | [odd even])) 131 | (defn odd-even-doseq-atomic [xs] 132 | (let [odd (AtomicInteger. 0) 133 | even (AtomicInteger. 0)] 134 | (doseq [x xs] 135 | (if (odd? x) 136 | (.getAndIncrement odd) 137 | (.getAndIncrement even))) 138 | [(.get odd) (.get even)])) 139 | 140 | (defn odd-even-doseq-array [xs] 141 | (let [odd (long-array [0]) 142 | even (long-array [0])] 143 | (doseq [x xs] 144 | (if (odd? x) 145 | (aset odd 0 (inc (aget odd 0))) 146 | (aset even 0 (inc (aget even 0))))) 147 | [(aget odd 0) (aget even 0)])) 148 | #_(odd-even-doseq-array xs-large) 149 | (defn odd-even-loop 150 | [xs] 151 | (loop [xs (seq xs) 152 | odd 0 153 | even 0] 154 | (if xs 155 | (if (odd? (first xs)) 156 | (recur (next xs) (inc odd) even) 157 | (recur (next xs) odd (inc even))) 158 | [odd even]))) 159 | (defn odd-even-chunked-loop 160 | [xs] 161 | (sv-loop [x xs 162 | :let [even 0, odd 0]] 163 | (if (odd? x) 164 | (recur even (inc odd)) 165 | (recur (inc even) odd)) 166 | [odd even])) 167 | #_(odd-even-chunked-loop xs) 168 | 169 | (defn tally-by [pred xs] 170 | (let [total (count xs) 171 | cnt (r/fold + (r/map (fn [_] 1) (r/filter pred xs)))] 172 | [cnt (- total cnt)])) 173 | #_(tally-by odd? xs) 174 | 175 | (comment 176 | ;; 10 million: 177 | (quick-bench (odd-even-reduce xs-large)) ;; 222ms 178 | (quick-bench (odd-even-reduce-count xs-large)) ;; 82ms 179 | (quick-bench (odd-even-reduce-prim-array xs-large)) ;; 94ms 180 | (quick-bench (odd-even-loop xs-large)) ;; 139ms 181 | (quick-bench (odd-even-loop-boxed xs-large)) ;; 182 | (quick-bench (odd-even-iter xs-large)) ;; 70ms 183 | (quick-bench (odd-even-chunked-loop xs-large)) ;; 65ms 184 | (quick-bench (odd-even-doseq-atomic xs-large)) ;; 103ms 185 | (quick-bench (odd-even-doseq-array xs-large)) ;; 73ms 186 | (quick-bench (odd-even-mutable xs-large)) ;; 70ms 187 | (quick-bench (tally-by odd? xs-large)) ;; 56ms 188 | ) 189 | 190 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 191 | ;; mapv - transient creation. 192 | 193 | (defn mapv-inc 194 | [xs] 195 | (mapv inc xs)) 196 | 197 | (comment 198 | (let [xs-small (vec (range 10))] 199 | (quick-bench (mapv-inc xs-small)))) 200 | 201 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 202 | ;; take-nth 203 | (defn take-nth-vec 204 | "Eager! outputs a vector." 205 | [n xs] 206 | (let [n-1 (long (unchecked-dec n))] 207 | (loop-it [x xs 208 | :let [i 0, out (transient [])]] 209 | (if (zero? i) 210 | (recur n-1 (conj! out x)) 211 | (recur (unchecked-dec i) out)) 212 | (persistent! out)))) 213 | (comment 214 | (quick-bench (into [] (take-nth 5) xs-large)) ;; 254ms 215 | (quick-bench (doall (take-nth 5 xs-large))) ;; 262ms 216 | (quick-bench (take-nth-vec 5 xs-large))) ;; 52ms 217 | 218 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 219 | ;; Other core: 220 | (defn interleave-fast 221 | [c1 c2] 222 | (loop-it [x1 c1, x2 c2 223 | :let [out (transient [])]] 224 | (recur (-> out (conj! x1) (conj! x2))) 225 | (persistent! out))) 226 | (comment 227 | (quick-bench (doall (interleave xs xs))) ;; 64ms 228 | (quick-bench (interleave-fast xs xs)) ;; 26ms 229 | (quick-bench (interleave-fast-nested xs xs)) ;; 26ms 230 | ) 231 | ;; Also: take, take-while 232 | 233 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 234 | ;; Partition-2 235 | (defn partition-2-reduce 236 | [pred xs] 237 | (mapv persistent! 238 | (reduce (fn [[truthy falsy] x] 239 | (if (pred x) [(conj! truthy x) falsy] 240 | [truthy (conj! falsy x)])) 241 | [(conj!) (conj!)] xs))) 242 | 243 | (defn partition-2 244 | [pred xs] 245 | (loop-it [x xs, :let [truthy (conj!), falsy (conj!)]] 246 | (if (pred x) 247 | (recur (conj! truthy x) falsy) 248 | (recur truthy (conj! falsy x))) 249 | [(persistent! truthy) (persistent! falsy)])) 250 | 251 | 252 | (comment 253 | (quick-bench (partition-2-reduce even? xs-large)) ;; 291ms 254 | (quick-bench (partition-2 even? xs-large))) ;; 176ms 255 | 256 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 257 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 258 | ;; Iterate multiple sequences: 259 | 260 | (defn transpose 261 | [c1 c2] 262 | (loop-it [x1 c1, x2 c2 263 | :let [out (transient [])]] 264 | (recur (conj! out [x1 x2])) 265 | (persistent! out))) 266 | 267 | (defn transpose-faster 268 | "Maybe returns a vector, maybe an IndexedSeq." 269 | [c1 c2] 270 | (if (and (counted? c1) (counted? c2)) 271 | (let [out-count (min (count c1) (count c2)) 272 | out (object-array out-count)] 273 | (loop-it [x1 c1, x2 c2 274 | :let [i 0]] 275 | (do 276 | (aset out i [x1 x2]) 277 | (recur (inc i))) 278 | (seq out))) 279 | (loop-it [x1 c1, x2 c2 280 | :let [out (transient [])]] 281 | (recur (conj! out [x1 x2])) 282 | (persistent! out)))) 283 | (comment (quick-bench (mapv vector xs xs)) 284 | (quick-bench (transpose xs xs)) 285 | (quick-bench (transpose-faster xs xs))) 286 | 287 | 288 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 289 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 290 | ;; Variable number of collections 291 | 292 | (defn mapv-fast-multi 293 | "NOTE: Can NOT deal with infinite sequences as arguments." 294 | [f & colls] 295 | (loop-it [xs (multi-iter colls) 296 | :let [out (conj!)]] 297 | (recur (conj! out (apply f xs))) 298 | (persistent! out))) 299 | 300 | #_(= (mapv vector xs xs xs xs) 301 | (mapv-fast-multi vector xs xs xs xs)) 302 | (comment (quick-bench (mapv vector xs xs xs xs)) 303 | (quick-bench (mapv-fast-multi vector xs xs xs xs))) 304 | 305 | (defn mapv-fast-lazy 306 | "NOTE: Can deal with infinite sequences as arguments. Just like mapv in core" 307 | [f & colls] 308 | (loop-it [xs (multi-iter-lazy colls) 309 | :let [out (conj!)]] 310 | (recur (conj! out (apply f xs))) 311 | (persistent! out))) 312 | #_(= (mapv vector xs xs xs xs) 313 | (mapv-fast-lazy vector xs xs xs xs)) 314 | (comment (quick-bench (mapv vector xs xs xs xs)) 315 | (quick-bench (mapv-fast-lazy vector xs xs xs xs))) 316 | 317 | ;; And we combine it: 318 | 319 | (defn mapv-fast 320 | "NOTE: Can deal with infinite sequences as arguments. 321 | Just like mapv in core" 322 | ([f coll] 323 | (loop-it [x coll, :let [out (conj!)]] 324 | (recur (conj! out (f x))) 325 | (persistent! out))) 326 | ([f c1 c2] 327 | (loop-it [x1 c1, x2 c2 328 | :let [out (conj!)]] 329 | (recur (conj! out (f x1 x2))) 330 | (persistent! out))) 331 | ([f c1 c2 c3] 332 | (loop-it [x1 c1, x2 c2, x3 c3 333 | :let [out (conj!)]] 334 | (recur (conj! out (f x1 x2 x3))) 335 | (persistent! out))) 336 | ([f c1 c2 c3 & colls] 337 | (loop-it [xs (if (counted? colls) 338 | (multi-iter (list* c1 c2 c3 colls)) 339 | (multi-iter-lazy (list* c1 c2 c3 colls))) 340 | :let [out (conj!)]] 341 | (recur (conj! out (apply f xs))) 342 | (persistent! out)) )) 343 | 344 | #_(apply mapv-fast #(-> %&) (repeat nil)) 345 | (comment (quick-bench (mapv vector xs xs xs xs)) ;; 1.28s 346 | (quick-bench (mapv-fast vector xs xs xs xs)) ;; 147ms 347 | (quick-bench (mapv2 vector xs xs xs xs)) ;; 348 | ) 349 | 350 | (comment (quick-bench (mapv vector xs xs xs)) ;; 110ms 351 | (quick-bench (mapv-fast vector xs xs xs)) ;; 23ms 352 | ) 353 | 354 | (comment (quick-bench (mapv vector xs xs)) ;; 96ms 355 | (quick-bench (mapv-fast vector xs xs)) ;; 20ms 356 | (quick-bench (mapv-new vector xs xs)) ;; 20ms 357 | ) 358 | 359 | (comment (quick-bench (mapv inc xs)) ;; 22ms 360 | (quick-bench (mapv-fast inc xs)) ;; 19ms 361 | ) 362 | 363 | 364 | 365 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 366 | ;; mapcatv ;; like mapcat but not lazy! 367 | (defn mapcatv 368 | "Mapcat. Eager and returns a vector. Slower if inner collection is small!" 369 | [f coll] 370 | (loop-it [xs coll, :let [out (transient [])]] 371 | (recur (loop-it [x (f xs), :let [out out]] 372 | (recur (conj! out x)) 373 | out)) 374 | (persistent! out))) 375 | 376 | (defn mapcatv-2 377 | [f coll] 378 | (loop-it [xs coll, :let [out (transient [])]] 379 | (recur (reduce conj! out (f xs))) 380 | (persistent! out))) 381 | #_(mapcatv vector (range 10)) 382 | #_(mapcatv-2 vector (range 10)) 383 | #_(mapcat vector (range 10)) 384 | 385 | (comment 386 | (quick-bench (into [] (mapcat vector) xs-large)) ;; 303ms 387 | (quick-bench (mapcatv vector xs-large)) ;; 527ms :( 388 | (quick-bench (mapcatv-2 vector xs-large))) ;; 263ms 389 | 390 | (comment 391 | (quick-bench (into [] (mapcat #(vector % % % %)) xs)) ;; 73ms 392 | (quick-bench (mapcatv #(vector % % % %) xs)) ;; 89ms 393 | (quick-bench (mapcatv-2 #(vector % % % %) xs))) ;; 69ms 394 | 395 | 396 | -------------------------------------------------------------------------------- /src/clj_bench/loop_it.clj: -------------------------------------------------------------------------------- 1 | (ns clj-bench.loop-it 2 | (:import 3 | (java.util Iterator))) 4 | 5 | (defn ensure-iter 6 | "Returns an iterator for x if it's not already one." 7 | ^Iterator [x] 8 | ;; CLJS: Check for nil -> niliter otherwise check if obj has: .hasNext & .next 9 | (if (instance? Iterator x) x (clojure.lang.RT/iter x))) 10 | 11 | #_(iterator-seq (ensure-iter "foo")) 12 | 13 | 14 | (defn multi-iter 15 | "Returns an iterator that 16 | - first returns a sequence of all the first elements 17 | - then a collection of all seconds elements 18 | - And so on... 19 | (Effectively providing you with a transposed view of the collection) 20 | Stops as soon as ONE of the collection doesn't have anymore elements." 21 | (^Iterator [colls] 22 | ;; Copied from clojure.lang.MultiIterator 23 | (let [iters ^{:tag "[Ljava.util.Iterator;"} (into-array Iterator 24 | (mapv ensure-iter colls))] 25 | (reify Iterator 26 | (hasNext [this] 27 | (let [len (alength iters)] 28 | (loop [i 0] 29 | (if (< i len) 30 | (if (.hasNext ^Iterator (aget iters i)) 31 | (recur (unchecked-inc i)) 32 | false) 33 | true)))) 34 | (next [this] 35 | (let [len (alength iters) 36 | arr (object-array len)] 37 | (dotimes [i len] 38 | (aset arr i (.next ^Iterator (aget iters i)))) 39 | (seq arr)))))) 40 | (^Iterator [xf colls] 41 | (clojure.lang.TransformerIterator/createMulti xf (map ensure-iter colls)))) 42 | 43 | (defmacro gen-inline-multi-iter 44 | "Generates an multi interator for the given Iterator array and given arity. 45 | The .next call returns vectors!" 46 | [arr arity] 47 | {:pre [(number? arity)]} 48 | (let [bindings (repeatedly arity #(gensym "it_"))] 49 | `(let ~(vec (mapcat (fn [bind arity] 50 | [bind `(aget ~(with-meta arr {:tag "[Ljava.util.Iterator;"}) 51 | ~arity)]) 52 | bindings (range arity))) 53 | (reify Iterator 54 | (~'hasNext [~'this] 55 | (and ~@(map #(-> `(.hasNext ~(with-meta % {:tag 'Iterator}))) 56 | bindings))) 57 | (~'next [~'this] 58 | [~@(map #(-> `(.next ~(with-meta % {:tag 'Iterator}))) 59 | bindings)]))))) 60 | #_ (macroexpand '(gen-inline-multi-iter arr 2)) 61 | 62 | (defn multi-iter-unrolled 63 | "Returns an iterator that 64 | - first returns a sequence of all the first elements 65 | - then a collection of all seconds elements 66 | - And so on... 67 | (Effectively providing you with a transposed view of the collection) 68 | Stops as soon as ONE of the collection doesn't have anymore elements." 69 | (^Iterator [colls] 70 | ;; Copied from clojure.lang.MultiIterator 71 | (let [iters ^{:tag "[Ljava.util.Iterator;"} (into-array Iterator (mapv ensure-iter colls))] 72 | (case (alength iters) 73 | 1 (gen-inline-multi-iter iters 1) 74 | 2 (gen-inline-multi-iter iters 2) 75 | 3 (gen-inline-multi-iter iters 3) 76 | 4 (gen-inline-multi-iter iters 4) ;; for 4 only about 12% faster... 77 | 5 (gen-inline-multi-iter iters 5) 78 | (reify Iterator 79 | (hasNext [this] 80 | (let [len (alength iters)] 81 | (loop [i 0] 82 | (if (< i len) 83 | (if (.hasNext ^Iterator (aget iters i)) 84 | (recur (unchecked-inc i)) 85 | false) 86 | true)))) 87 | (next [this] 88 | (let [len (alength iters) 89 | arr (object-array len)] 90 | (dotimes [i len] 91 | (aset arr i (.next ^Iterator (aget iters i)))) 92 | (seq arr))))))) 93 | (^Iterator [xf colls] 94 | (clojure.lang.TransformerIterator/createMulti xf (map ensure-iter colls)))) 95 | 96 | (defn multi-iter-lazy 97 | "Just like mult-iter but lazy." 98 | ^Iterator [colls] 99 | (let [iters (map ensure-iter colls)] 100 | (reify Iterator 101 | (hasNext [this] 102 | (loop [xs (seq iters)] 103 | (if xs 104 | (if (.hasNext ^Iterator (first xs)) 105 | (recur (next xs)) 106 | false) 107 | true))) 108 | (next [this] 109 | (map #(.next ^Iterator %) iters))))) 110 | 111 | (defmacro loop-it 112 | "Uses iterator to iterate over all given collections in bindings. 113 | Stops as soon as one collection has no more elements. 114 | Requires a `:let []` as the last two elements of the 115 | bindings. 116 | body is run with all bindings bound to the element of the collection 117 | finish is run on the last iteration when there are no more elements. 118 | Example: 119 | (loop-it [^long a xs0 120 | ^long b xs1 121 | ^long c xs2 122 | :let [sum 0, prod 1]] 123 | (recur (+ sum a b c) (* prod a b c) 124 | {:sum sum, :prod prod})" 125 | [bindings body finish] 126 | {:pre [(vector? bindings) (even? (count bindings)) 127 | (vector? (last bindings)) (= :let (last (butlast bindings)))]} 128 | (let [it-binds (butlast (butlast bindings)) 129 | sym-binds (take-nth 2 it-binds) 130 | colls (take-nth 2 (rest it-binds)) 131 | iter-syms (repeatedly (count sym-binds) #(gensym "iter"))] 132 | `(let ~(vec (mapcat (fn [it coll] 133 | [it `(ensure-iter ~coll)]) 134 | iter-syms colls)) 135 | (loop ~(vec (last bindings)) 136 | (if (and ~@(map (fn [it] `(.hasNext ~it)) iter-syms)) 137 | (let ~(vec (mapcat (fn [bind it] 138 | [bind `(.next ~it)]) 139 | sym-binds iter-syms)) 140 | ~body) 141 | ~finish))))) 142 | 143 | -------------------------------------------------------------------------------- /src/clj_bench/map_chunking.clj: -------------------------------------------------------------------------------- 1 | (ns clj-bench.map-chunking 2 | "See: 3 | https://dev.clojure.org/jira/browse/CLJ-2346" 4 | (:require [criterium.core :as crit])) 5 | 6 | (defn doall-fast 7 | [s] 8 | (when-some [s (seq s)] 9 | (if (chunked-seq? s) 10 | (doall-fast (chunk-rest s)) 11 | (doall-fast (next s))))) 12 | 13 | (defn chunked-map [f coll] 14 | (when-some [s (seq coll)] 15 | (if (chunked-seq? s) 16 | (let [cf (chunk-first s) 17 | b (chunk-buffer (count cf))] 18 | (.reduce cf (fn [b x] (chunk-append b (f x)) b) b) ;; reduce instead of dotimes 19 | (chunk-cons (chunk b) (chunked-map f (chunk-rest s)))) 20 | (cons (f (first s)) (map f (rest s)))))) 21 | 22 | (defn map-orig 23 | [f coll] 24 | (when-let [s (seq coll)] 25 | (if (chunked-seq? s) 26 | (let [c (chunk-first s) 27 | size (int (count c)) 28 | b (chunk-buffer size)] 29 | (dotimes [i size] 30 | (chunk-append b (f (.nth c i)))) 31 | (chunk-cons (chunk b) (map-orig f (chunk-rest s)))) 32 | (cons (f (first s)) (map-orig f (rest s)))))) 33 | 34 | (let [xs (vec (range 4))] 35 | (crit/quick-bench (map-orig inc xs)) 36 | (crit/quick-bench (chunked-map inc xs))) 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/clj_bench/misc.clj: -------------------------------------------------------------------------------- 1 | (ns clj-bench.misc 2 | (:require [criterium.core :as crit])) 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/clj_bench/sort_by.clj: -------------------------------------------------------------------------------- 1 | (ns clj-bench.sort-by 2 | (:require 3 | [criterium.core :refer :all])) 4 | 5 | (defn sort-by- 6 | ([keyfn coll] 7 | (sort-by- keyfn compare coll)) 8 | ([keyfn ^java.util.Comparator comp coll] 9 | (if (seq coll) 10 | (let [ary (object-array (count coll))] 11 | (loop [i 0 xs (seq coll)] 12 | (when xs 13 | (let [x (first xs)] 14 | (aset ary i (object-array [(keyfn x) x])) 15 | (recur (inc i) (next xs))))) 16 | (. java.util.Arrays 17 | (sort ary (fn [x y] (. comp (compare (aget ^{:tag "[Ljava.lang.Object;"} x 0) 18 | (aget ^{:tag "[Ljava.lang.Object;"} y 0)))))) 19 | (map (fn [x] (aget ^{:tag "[Ljava.lang.Object;"} x 1)) ary)) 20 | ()))) 21 | 22 | 23 | (comment 24 | (def xs (repeatedly 500000 #(-> {:x (rand-int 1000)}))) 25 | 26 | (with-progress-reporting 27 | (quick-bench (sort-by- :x xs) :verbose)) 28 | 29 | (with-progress-reporting 30 | (quick-bench (sort-by :x xs) :verbose))) 31 | 32 | -------------------------------------------------------------------------------- /src/clj_bench/spy_test.clj: -------------------------------------------------------------------------------- 1 | (ns clj-bench.spy-test 2 | (:require 3 | [spy.core :refer [spy]])) 4 | 5 | (defn foo 6 | [x y] 7 | (spy [x y]) 8 | (let [z (* x y)] 9 | (spy z))) 10 | #_(spy [x y]) 11 | #_(apply foo (spy [x y])) 12 | 13 | (defn bar [x] 14 | {:post [(spy bar %)]} 15 | (spy x) 16 | (* x x)) 17 | 18 | (comment 19 | (foo 1 2) 20 | (bar 22) 21 | 22 | ) 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | (comment 50 | ;; In CLJS: 51 | 52 | (defn fooo [x] 53 | (spy 'fooo x y)) 54 | 55 | (defn bar [y] 56 | (spy 'bar x y)) 57 | ) 58 | 59 | 60 | 61 | 62 | (comment 63 | 64 | (spy :all x) 65 | 66 | ) 67 | 68 | -------------------------------------------------------------------------------- /src/clj_bench/vec_reduce.clj: -------------------------------------------------------------------------------- 1 | (ns clj-bench.vec-reduce 2 | "Custom for PV's." 3 | (:require [clojure.walk :as walk]) 4 | (:import 5 | (clojure.lang PersistentVector))) 6 | 7 | (defn prefix-recur 8 | [form & prefixes] 9 | (walk/postwalk 10 | (fn [x] 11 | (if (seq? x) 12 | (let [[call & args] x] 13 | (if (= 'recur call) 14 | (list* 'recur (concat prefixes args)) 15 | x)) 16 | x)) 17 | form)) 18 | 19 | (defmacro sv-loop 20 | "Single vector loop using chunkes similar to doseq. 21 | Note: Inflexible and not much faster than using iterators. So don't use this." 22 | [[bind vec let-kw loop-bind] body finish] 23 | {:pre [(= let-kw :let) (vector? loop-bind)]} 24 | (assert (every? symbol? (take-nth 2 loop-bind))) 25 | (let [chunk- (with-meta (gensym "chunk_") 26 | {:tag 'clojure.lang.IChunk}) 27 | i- (gensym "i_") 28 | seq- (gensym "seq_") 29 | count- (gensym "count_")] 30 | `(let [~seq- (seq ~vec)] 31 | (assert (chunked-seq? ~seq-)) 32 | (loop [~seq- ~seq- 33 | ~chunk- nil 34 | ~count- 0 35 | ~i- 0 36 | ;; Other loop bind 37 | ~@loop-bind] 38 | (if (< ~i- ~count-) 39 | (let [~bind (.nth ~chunk- ~i-)] 40 | ~(prefix-recur body seq- chunk- count- `(unchecked-inc ~i-))) 41 | (if (some? ~seq-) 42 | (if (chunked-seq? ~seq-) 43 | (let [c# (chunk-first ~seq-)] 44 | (recur (chunk-next ~seq-) c# (int (count c#)) 0 45 | ;; TODO: Support destructing here? 46 | ~@(take-nth 2 loop-bind))) 47 | (let [~bind (first ~seq-)] 48 | ~(prefix-recur body `(next ~seq-) nil 0 0))) 49 | ~finish)))))) 50 | -------------------------------------------------------------------------------- /src/spy/core.clj: -------------------------------------------------------------------------------- 1 | (ns spy.core) 2 | 3 | (defn- get-hostname [] 4 | (.. java.net.InetAddress getLocalHost getHostName)) 5 | 6 | (def debug? 7 | "ADAPT ME!!" 8 | (delay (or (= "dev" (System/getProperty "nomad.env")) 9 | (= (get-hostname) "sky")))) 10 | 11 | (defonce spy-data (atom {#_ns #_{form {line data}}})) 12 | #_(reset! spy-data {}) 13 | 14 | (defn find-form 15 | [data form seek-line] 16 | ;; If form is nil, we seek the closest line 17 | ;; If form is given, we seek for the closest which have the given form 18 | (let [filt (if (some? form) #(= % form) (constantly true)) 19 | [form line] 20 | (reduce-kv 21 | (fn [[found-form found-line] form line->data] 22 | (reduce-kv 23 | (fn [[curr-form curr-line] line-candidate _] 24 | (if (and (filt form) ;; We have a match: See if it's closer than prev match 25 | (< (Math/abs ^long (- seek-line line-candidate)) 26 | (Math/abs ^long (- curr-line line-candidate)))) 27 | [form line-candidate] 28 | [curr-form curr-line])) 29 | [found-form found-line] line->data)) 30 | [form 0] data)] 31 | (get-in data [form line]))) 32 | 33 | (defmacro spy 34 | "Always gets run. Maybe with spying, maybe not. 35 | Returns the result of the last argumennt" 36 | [& forms] 37 | (if @debug? 38 | (let [line (:line (meta &form)) 39 | local-bindings (set (keys &env)) 40 | ns *ns*] 41 | (if (and (some? forms) 42 | (not (empty? local-bindings))) 43 | `(let [res# (do ~@forms)] 44 | (swap! spy-data assoc-in [~ns (quote ~forms) ~line] res#) 45 | res#) 46 | `(find-form (get (deref spy-data) ~ns) (quote ~forms) ~line))) 47 | `(do ~@forms))) 48 | 49 | (defmacro spyo 50 | "Does NOT emit forms unless debug is true." 51 | [& forms] 52 | (when @debug? 53 | (let [line (:line (meta &form)) 54 | local-bindings (set (keys &env)) 55 | ns *ns*] 56 | (if (and (some? forms) 57 | (not (empty? local-bindings))) 58 | `(let [res# (do ~@forms)] 59 | (swap! spy-data assoc-in [~ns (quote ~forms) ~line] res#) 60 | res#) 61 | `(find-form (get (deref spy-data) ~ns) (quote ~forms) ~line))))) 62 | 63 | 64 | --------------------------------------------------------------------------------