processing / p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. http://twitter.com/p5xjs —
http://p5js.org/
GNU Lesser General Public License v2.1
21.4k stars 3.28k forks source link

[p5.js 2.0 RFC Proposal]: Using a separate math library for handling p5.js's math operations #6765

Open RandomGamingDev opened 7 months ago

RandomGamingDev commented 7 months ago

Increasing access

As discussed in #6527: Using another library would mean a better documented and managed library with more features for p5.js, but it'll also be more performant, and we could even choose a library that can utilize the GPU for especially heavy operations. It would also make p5.js much more powerful and easier to deal with for those who want to use it for things like 4d scenes or other areas involving math which includes things from basic sites to fully fledged games and demos.

Which types of changes would be made?

Most appropriate sub-area of p5.js?

What's the problem?

The current p5.js math component is heavily cluttered as discussed at https://github.com/processing/p5.js/issues/6527 & https://github.com/processing/p5.js/issues/6527#issuecomment-1793477773 and isn't nearly as optimized as it could be which makes it hard to not only use if you're trying to understand and interact with the code, but also to contribute to, especially for a library designed to increase accessibility to beginners. Plus, it's hard to integrate p5.js with other math libraries when you need any math that's more complex, for instance if someone wanted to do something that involved linear algebra, or calculus that isn't included in p5.js, like 4d scenes.

What's the solution?

The solution would be utilizing another math library using another library would mean a better documented and managed library with more features for p5.js, but it'll also be more performant, and we could even choose a library that can utilize the GPU for especially heavy operations.

Pros (updated based on community comments)

Example list:

Cons (updated based on community comments)

Proposal status

Under review

limzykenneth commented 7 months ago

I'm generally hesitant to use an external math library for p5.js for a few reasons, mainly surrounding the use of external dependencies in p5.js. Where possible I would like to avoid external dependencies. We have external dependency on Opentype.js and it is definitely giving quite a bit of problems, including those listed below.

  1. Larger bundle size - A lot of the bundle size of p5.js is taked up by Opentype.js and introducing another external dependency will likely make this worse. One of the goals of p5.js 2.0 is to optimize bundle size and even things like Opentype.js I'm thinking of refactoring it out or moving it into an optional component to save on size.
  2. Longer term support risk - There are risk that whatever external library we end up using may fall out of support in the future, hamstringing us in terms of keeping things up to date. Many of the dependencies we use already have this problem which p5.js 2.0 is an opportunity to address them.

Most math libraries probably include things that we may not need for p5.js, at least on a basic level. I think at this stage it would be better if we can figure out what are the math features as well as interfaces that p5.js 2.0 needs first, whether it is multidimentional vectors and matrices, in-depth linear algebra, hardware acceleration, etc.

I suspect for a basic level we don't need full linear algebra functionalities and we can consider code implementation in other libraries for the simpler stuff that we do need and implementing it ourselves, eg. taking vector implementation code from Three.js and implementing it in our own module without explicitly including Three.js as a dependency.

To copy and paste from the current RFC: A new math module will be implemented. The requirements of this new math module are:

Especially the last point, if we standardize the end user API of how math works in p5.js 2.0, addon libraries can be created to act as a bridge between any external math libraries and p5.js by overwriting the exsting math implementation or adding additional APIs.

Let me know if that made sense.

nickmcintyre commented 7 months ago

@RandomGamingDev thanks for bringing this up. You've pointed out a clear need for a refactor/rewrite, but adding a separate math library feels like a disproportionate solution. +1 to pretty much everything @limzykenneth said.

Functions such as cos() are generally fine as-is. p5.Matrix and p5.Vector could use some TLC as you've mentioned. Overall, the p5.js core only needs a few classes with a few dozen methods. I believe it's actually more accessible to contributors for those implementations to live in the p5.js repo. We should definitely aim to make them clean and performant.

@RandomGamingDev what do you think about opening a couple of related issues?

RandomGamingDev commented 7 months ago

Overall, the p5.js core only needs a few classes with a few dozen methods. I believe it's actually more accessible to contributors for those implementations to live in the p5.js repo. We should definitely aim to make them clean and performant.

I disagree with this point since I don't see how an already implemented library with proper documentation would be any less accessible compared to a custom solution built from the ground up and even more so if wrap the API using p5.js.

Larger bundle size - A lot of the bundle size of p5.js is taked up by Opentype.js and introducing another external dependency will likely make this worse. One of the goals of p5.js 2.0 is to optimize bundle size and even things like Opentype.js I'm thinking of refactoring it out or moving it into an optional component to save on size.

Math libraries like NumJs have tiny sizes like 720kb unpacked for NumJs in particular: https://www.npmjs.com/package/numjs

Longer term support risk - There are risk that whatever external library we end up using may fall out of support in the future, hamstringing us in terms of keeping things up to date. Many of the dependencies we use already have this problem which p5.js 2.0 is an opportunity to address them.

It should be safe to rely on libraries like NumJs since they should be supported for quite some time, not to mention that even if long term support is stopped, we will most likely already have all the features we need to not to mention that forks will most likely pop up considering its size as well as the fact that the plan would be to wrap the entire API with p5.js meaning that it'd be much easier to switch between math libraries.

Most math libraries probably include things that we may not need for p5.js, at least on a basic level. I think at this stage it would be better if we can figure out what are the math features as well as interfaces that p5.js 2.0 needs first, whether it is multidimentional vectors and matrices, in-depth linear algebra, hardware acceleration, etc.

I suspect for a basic level we don't need full linear algebra functionalities and we can consider code implementation in other libraries for the simpler stuff that we do need and implementing it ourselves, eg. taking vector implementation code from Three.js and implementing it in our own module without explicitly including Three.js as a dependency.

To copy and paste from the current RFC: A new math module will be implemented. The requirements of this new math module are:

  • Unified vector and matrices support with compatible API with ml5.js.
  • Explore reasonable performance optimizations through the use of specific algorithms, GPU implementation, or others.
  • Possibility for addon libraries to provide own implementation (so that any external libraries can be made compatible without being implemented internally by p5.js).

Especially the last point, if we standardize the end user API of how math works in p5.js 2.0, addon libraries can be created to act as a bridge between any external math libraries and p5.js by overwriting the exsting math implementation or adding additional APIs.

Honestly, I don't see an issue with implementing more complex and math heavy features if it can interact with external math libraries properly instead of the messy system currently being employed. However, this is assuming that it can be properly maintained and is worth doing so. One of the main reasons why I'm pushing for incorporating an external math library into p5.js is due to the issue of whether or not it's worth it to get people working on a largely graphics focused library to redo the wheel by rewriting core math code that's already been written before costing a lot of manpower as well as not guaranteeing a satisfactory level of code quality. The current p5.Math code, for me shows that this, if attempted, will be quite difficult and might not even work which would leave p5.js in an even worse off position.

@RandomGamingDev what do you think about opening a couple of related issues?

  • Add a contributor code style guide (e.g., Airbnb unless it's a performance optimization)
  • Update the math module starting with the requirements @limzykenneth shared

I agree that if we don't add a math library, this would probably be our best bet and I'd be fine with adding these issues. However, I do still feel like reimplementing the math implemented in other libraries and trying to get a largely graphics focused group of contributors to have to work on the math library alongside graphics code at the same time that they code everything will cost a lot of unnecessary manpower as well as not guaranteeing a satisfactory level of code quality.

limzykenneth commented 7 months ago

It should be safe to rely on libraries like NumJs since they should be supported for quite some time, not to mention that even if long term support is stopped, we will most likely already have all the features we need to not to mention that forks will most likely pop up considering its size as well as the fact that the plan would be to wrap the entire API with p5.js meaning that it'd be much easier to switch between math libraries.

I think for me Numjs more or less made the point of why I'm hesitant to incorporate external libraries. 720kb is somewhat significant in terms of file size, and to give some perspective, p5.js unminified is currently 4.34mb which 720kb will be about 16% of the overall size (granted not all 720kb will be packaged in and is likely an overestimate, it may be worth figuring out what actual impact it has on size). Numjs also appears already not under active maintenance for at least 2 years with last commit 3 years ago and last published on NPM 2 years ago. This is quite significant in the JavaScript ecosystem, and also means any issue we have that can be traced back to Numjs we don't have reasonable means to fix them.

The main point I'm trying to make is not to implement all the complex and heavy math features all by ourselves but rather to identify what actual math features we actually need first. Eg. we don't need math expression evaluation or expression derivative (so that's one large part of Math.js we don't need for example), we may or may not need full matrix operations, etc. Once we have an idea what we actually need then we can evaluate how we actually implement it: use available browser implementations, take existing implementations from other libraries, or if it is really necessary use external libraries. Without figuring out what we need at this stage we risk bloating the library with features that is never or very seldom used.

RandomGamingDev commented 7 months ago

I think for me Numjs more or less made the point of why I'm hesitant to incorporate external libraries. 720kb is somewhat significant in terms of file size, and to give some perspective, p5.js unminified is currently 4.34mb which 720kb will be about 16% of the overall size (granted not all 720kb will be packaged in and is likely an overestimate, it may be worth figuring out what actual impact it has on size). Numjs also appears already not under active maintenance for at least 2 years with last commit 3 years ago and last published on NPM 2 years ago. This is quite significant in the JavaScript ecosystem, and also means any issue we have that can be traced back to Numjs we don't have reasonable means to fix them.

While size should be a concern I don't think that numjs, especially with the limited amount of features we'll be using will pose an issue. Also, your point about NumJs while partially valid doesn't really apply since the API would be implemented in a way where it would all be under the p5.js namespace and because we might very likely do something similar to three.js where choose take certain parts of it. Either that, or we import it as normal.

The main point I'm trying to make is not to implement all the complex and heavy math features all by ourselves but rather to identify what actual math features we actually need first. Eg. we don't need math expression evaluation or expression derivative (so that's one large part of Math.js we don't need for example), we may or may not need full matrix operations, etc. Once we have an idea what we actually need then we can evaluate how we actually implement it: use available browser implementations, take existing implementations from other libraries, or if it is really necessary use external libraries. Without figuring out what we need at this stage we risk bloating the library with features that is never or very seldom used.

I'm fine with this part if the standardized interface for interacting with NumJs idea is implemented, but my main concern with that, again, is the issue of the unnecessary expenditure of manpower and issues with maintaining code quality.

limzykenneth commented 7 months ago

@RandomGamingDev There is ultimately going to be some level of engineering involve unless we don't even implement interfaces to any math operations and let users use external math libraries directly. I wouldn't worry too much about time and effort spent on this in this case as long as it is providing value (which I believe it will). For code quality, you can always be our check when things feel like it is going too out of hand, and I would really appreciate that extra perspective as well.

I'm fine with this part if the standardized interface for interacting with NumJs idea is implemented

General compatibility with say NumJs or Math.js is something I would like to aim for as well so it can be straightforward to bring in any external library, even without additional glue code in the form of an addon library, and have it be usable with most if not all p5.js functions. This should definitely be looked into.

aferriss commented 7 months ago

Setting aside the performance and code organization arguments, what are the specific use cases that bringing a separate math library in would enable. For example, what would a user be able to do with linear algebra or calculus functions that they cannot do now?

Second, do we have any way of knowing how much demand exists for the kinds of advanced math features that would come with a separate library? Anecdotally, are these features requested often by students or other people on forums / github / discord?

Lastly, can we benchmark data from different browsers / devices that can tell us specifically which parts of the p5 math library are slow and what needs improving? Then also some comparison with the library / optimization being proposed. It would be good to know what is in most need of help.

In general I think it would be good to get more specifics about the current perf and usage to help come to a decision.

RandomGamingDev commented 6 months ago

Setting aside the performance and code organization arguments, what are the specific use cases that bringing a separate math library in would enable. For example, what would a user be able to do with linear algebra or calculus functions that they cannot do now?

It wouldn't make anything currently impossible possible, but it'd increase the productivity and ease of contribution for those contributing to p5.js as well as the ease of use for anyone who just wants to do something involving linear algebra with p5.js

Second, do we have any way of knowing how much demand exists for the kinds of advanced math features that would come with a separate library? Anecdotally, are these features requested often by students or other people on forums / github / discord?

While I haven't done an interview, I know that p5.Math is oftentimes used for mathematical visualizations, as can be seen from the popular series "The Coding Train" which largely focuses on p5.js and, alongside many other mathematical displays would benefit massively. The performance, while it'd be good should be basically negligible so we can ignore that part for now.

Lastly, can we benchmark data from different browsers / devices that can tell us specifically which parts of the p5 math library are slow and what needs improving? Then also some comparison with the library / optimization being proposed. It would be good to know what is in most need of help.

I didn't do it for multiple browsers, but it should be around the same for most. The benchmarks can be found in this comment alongside a description and explanation for them: https://github.com/processing/p5.js/issues/6527#issuecomment-1937994662

davepagurek commented 6 months ago

While not addressing every point in the proposal, an option brought up in #6527 is to basically keep our same API, same friendly errors and such, but swap out our vector/matrix implementations with a library to reduce some of the complexity of our own codebase and the scope of things we need to test, while also getting some performance gains (@RandomGamingDev got some good metrics on what those gains could be in the previously linked comment.) This feels like a sort of lower-risk change that doesn't affect p5's offerings to users, and costs less engineering time by keeping the same API. It might be a good GSoC-sized project too, to take some load off of maintainers.

mohmoh412 commented 6 months ago

Hello Community,

My name is Mohini, and I am a self taught programmer. I've taken the time to thoroughly read the discussion and the related issues including the performance comparison provided.

I do feel that the integration of an external library like glMatrix for vector and matrix calculations is a good strategic step towards enhancing the mathematical capabilities of p5.js. Based on the performance benchmarks shared, it's clear that glMatrix could significantly boost the efficiency for intensive applications such as 3D graphics rendering, without compromising too much on memory usage.

I also believe that the adoption of glmatrix, or a similar high-performance library, will help in providing readability and ease of use for beginners while also offering advanced mathematical functionalities to seasoned programmers for complex projects.

Integrating an external library for vector and matrix operations will be a good first step, and in terms of scalability and long term goals, it would also provide an opportunity to reevaluate and possibly reorganise the existing math library structure, by consolidating related functionalities. This would ensure that the library remains intuitive and accessible, all while keeping the core values of simplicity and accessibility uncompromised.

I would like to add that having comprehensive guidelines and testing would allow us to identify any inefficiencies and set benchmarks for the implementations to help maintain the standard and efficiency of the math library in the long run.

I started my programming journey with p5.js and I am more than happy to have this as my first open source contribution .I'm also planning to apply for GSoC 2024, and would like to incorporate this project in my proposal. If there are any additional issues or improvements I haven't considered, I'm all ears and would really like to hear your inputs and suggestions.