7 ms·
This was one of the more interesting software talks I've listened to recently. I like that it was very real - there are serious, serious problems with Node.js,
by thosakwe 8y ago
This was one of the more interesting software talks I've listened to recently. I like that it was very real - there are serious, serious problems with Node.js, and the fact that even the creator acknowledges these problems caught my attention.
I'm also a long-time user of Dart, so when he brought that up, and compared TypeScript to its shortcomings, I definitely agreed.
That being said, even with the Deno project, I'm not so sure what can come in terms of performance and security from running JavaScript outside of a browser. The choice of V8 also raises concerns for me about build systems. He mentioned the failing of GYP, but anything using the same build toolchain as Chromium always introduces a wealth of complexity for anyone building said software, as not only do you need Google-specific build tools, but also very specific configuration including Python.
It will be interesting to see what comes in the future.
If it were up to me (which I guess it isn't), I'd probably prioritize portability/less complex builds, built-in FFI, a flat module system, and optimizing calls to C from JS.
- mschuetz 8y ago> performance and security from running JavaScript outside of a browser. I'm just now building a node app to filter point clouds, so lots of number crunching. In two days I've got something in javascript that's faster than the C++ solution I've been working on for a week. Mostly because javascript/node makes it trivial to parallelize file IO while doing work in the main thread. This app reads 13 million points from 1400 files (~200mb), filters all points within a clip region, and writes the 12 million resulting points in a 300MB file, all in 1.6 seconds. (File reads were cached by OS and/or disk due to repeated testing, but file writes probably not) My personal conclussion is that javascript can rival or even exceed the performance of C++, not because it's inherently faster, it's obviously not, but because it makes it much easier to write fast code. For the highest possible performance you'll defenitely want to use C++ but sometimes you'll have to spend multiple times the work to get there.
- chrisco255 8y agoRight, V8 works great at optimizing JS and it handles streams great. Productivity is one of the most important factors to think about when building software systems since human time is much more expensive than CPU cycles. That's why Node.js works great.
- maerF0x0 8y agoThis fails from the false dichotomy of speed of execution vs speed of development (which includes fixing bugs). Well written languages optimize to a certain weighted preference of the two and some languages deliver more of _both_ than others. For example; Typescript is fast to write. and Golang is reasonably quick to write, _and_ execute. Both should have ~15% less bugs than javascript, potentially making them faster to develop (where bugs matter).
- ninjakeyboard 8y agowhat is the 15% figure from? I'm suddenly working with a dynamically typed language (elixir) coming from scala and I do find more bugs. Would like some hard evidence to support that so just curious.
- maerF0x0 8y ago15% is from this paper as I recall it: http://ttendency.cs.ucl.ac.uk/projects/type_study/documents/type_study.pdf http://ttendency.cs.ucl.ac.uk/projects/type_study/documents/... https://blog.acolyer.org/2017/09/19/to-type-or-not-to-type-quantifying-detectable-bugs-in-javascript/ https://blog.acolyer.org/2017/09/19/to-type-or-not-to-type-q...
- ninjakeyboard 8y agothanks!
- pera 8y agoHave you tried to use Dialyzer or Dialyxir and typespecs?
- ninjakeyboard 8y agono. I probably should.
- 8y ago
- blattimwind 8y ago> (File reads were cached by OS and/or disk due to repeated testing, but file writes probably not) Unless you flush the pages manually, your dirty pages (written files) live on long after your process died. Depending on system and configuration, minutes or even hours can pass before they are flushed to disk.
- mschuetz 8y agoDo you know about best practices to benchmark with uncached data? It's something I've been wondering about for a long time and I've seen many attempts at benchmarking things without regard for disk caching. e.g. benchmarking in-memory data bases to out-of-core databases but because of caching due to repeated runs, the results were meritless since the out-of-core databases had their stuff in memory as well.
- zbjornson 8y agoTake a look at https://github.com/Feh/nocache https://github.com/Feh/nocache. It works effectively for reads. I don't know about writes.
- brlewis 8y agoDid you use typed arrays, or did the benefit of async I/O outweigh the cost of using double-precision floats for everything?
- mschuetz 8y agoI'm reading the values directly from the Buffer object that is returned from fs.readFile using buffer.readUInt32LE and buffer[index], then convert the values to doubles to do the hit-test and if it succeeds, it's immediately written to the output buffer. The nodejs Buffer object is a subclass of Uint8Array as far as I know. On writing, the double coordinate values are transformed back into a fixed-precision integer format and stored in the output Buffer object. I'm not generating an intermediate buffer since that does decrease performance a bit. It's directly from input buffer to output buffer. Output buffer is initially allocated with the same size as the input, and before sending it to the output stream it's cut to the actual size. One thing I've previously learned and which has shown to be still true is that writing individual bytes to a buffer is faster than writing integers. So originally I did this: outBuffer.writeInt32LE(ux, outOffset + 0); But this turned out to be significantly faster. (~20%) // do once let tmpBuffer = new ArrayBuffer(4); let tmpUint32 = new Uint32Array(tmpBuffer); let tmpUint8 = new Uint8Array(tmpBuffer); // do many times tmpUint32[0] = ux; outBuffer[outOffset + 0] = tmpUint8[0]; outBuffer[outOffset + 1] = tmpUint8[1]; outBuffer[outOffset + 2] = tmpUint8[2]; outBuffer[outOffset + 3] = tmpUint8[3];
- zbjornson 8y agoJust constructing a Uint32Array view of the buffer and accessing values by index way(!) faster than using the buffer.read* methods. Likewise, you don't need to copy bytes in your last code sample. You can copy uint32s.
- mschuetz 8y agoThe buffer contains not just integer but also byte, unsigned byte, short, etc. Due to this, the buffer length may not be a multiple of 4, and Uint32Array views can only be constructed on buffers with a length of a multiple of 4. Edit: Also, the stride from one record to the next can be anything, e.g. 15. An Uint32Array would need a stride of 4 or a multiple of 4 to be useful. Edit2: I could try to create 4 Uint32Arrays with byteOffsets 0 to 3, and with a view length of a multiple of 4, then use the one that works with the attribute I'm currently processing. Not sure if that's really going to be faster but who knows.
- ex3ndr 8y agoCan you share some sources? I tried to process simple CSV files in a very straight forward (but async) way and got reading 200mb CSV and just splitting it to columns (with simple split by comma) takes ~10 seconds. Also simplest HTTP request in express is handled in several ms and that's A LOT in my opinion.
- mschuetz 8y agoI don't really have any explanatory sources at hand, just the source code here: https://github.com/potree/PotreeServer/blob/redo/src/RegionsFilter.js https://github.com/potree/PotreeServer/blob/redo/src/Regions... Points of interest: Schedule files to be loaded. This will usually load around 1000 files: https://github.com/potree/PotreeServer/blob/redo/src/RegionsFilter.js#L283 https://github.com/potree/PotreeServer/blob/redo/src/Regions... Whenever a file is loaded, iterate through the points in it, do the filtering and write the results to the output file: https://github.com/potree/PotreeServer/blob/redo/src/RegionsFilter.js#L286 https://github.com/potree/PotreeServer/blob/redo/src/Regions... Wait until all files were loaded and processed: https://github.com/potree/PotreeServer/blob/redo/src/RegionsFilter.js#L399 https://github.com/potree/PotreeServer/blob/redo/src/Regions... Wait until the output was written to disk: https://github.com/potree/PotreeServer/blob/redo/src/RegionsFilter.js#L401 https://github.com/potree/PotreeServer/blob/redo/src/Regions... What happens is that ~1000 files will be loaded in the background, points are filtered in the main thread and even while some files are still being loaded, we already start writing the results to the output file. > I tried to process simple CSV files in a very straight forward (but async) way and got reading 200mb CSV and just splitting it to columns (with simple split by comma) takes ~10 seconds. CSV may be much bigger challenge since it's ASCII data. That always tends to take multiple times longer.
- sebringj 8y ago"I'm not sure what can come of performance and security running JavaScript outside of a browser" well we already know about performance. Ryan was mentioning and demonstrating that JS is in a sandbox already and if modifying node to have message passing with dispatchers mirroring on native and js sides, you in effect have very tight security as you are strictly allowing only sys calls that are going through a single point and can be managed through a single point. Seems like that one is figured out with Deno.
- vanderZwan 8y ago> the fact that even the creator acknowledges these problems caught my attention. Not to take anything away from Ryan Dahl's ability to reflect and be open about what he considers his design mistakes, but it probably also helps a bit that he walked away for quite a while before coming back. A bit of distance helps in these matters.
- hliyan 8y agoQuestion: have you written any server side Dart? I'm sold on the client side with Flutter.