Comments (6)
Just a thought: Why not defining all units an app may use in a yml file, which gets parsed exactly once during startup. The parser then creates Unit singletons for all defined units...
from quantify.
Just finished refactoring Dimensions class with its notoriously slow #to_hash method: https://github.com/cblock/quantify/
This brings down spec runtime from ~16 secs to ~5 secs already. The benchmark is even better (Quantity#to_si uses #to_hash internally):
user system total real
[ Quantity#to_si ]
11.860000 0.100000 11.960000 ( 11.969939)
user system total real
[ Quantity#to_si ]
0.970000 0.000000 0.970000 ( 0.972983)
Let me know what you think. Should I send you a pull request for the main branch?
from quantify.
Hey Carsten. Sounds great, certainly send a pull request.
I like the idea of specifying units once on initialization. That was my intention really when using the config files, although given the 'default' configuration (currently, all units), a custom configuration might involve dumping a load of previously defined units which I don't think is very nice. Trouble is, there has to be some default units (and dimensions), for example, the SI units against which all other units are referenced.
I think I would prefer a system where a smaller set of required units is always instantiated and others can be pulled in if desired, perhaps in a modular fashion (require 'cgs', require 'imperial', etc.), or individually defined. YAML format sounds fine. Currently, you can override the default config by running additional config in an initializer (or elsewhere). I've basically never been able to decide on the best solution or anticipate what would suit others best (convention or configuration?).
The Dimension#to_hash method is mostly used in operations (multiply, divide, etc) between two dimensions. I think in most cases it is passed in to the private #enumerate_base_quantities method which alters the base quantities on the receiver. The memoized hash would probably need refreshing at the end of that method.
I have thought about using singletons to represent units but never got to a satisfactory point. At present, an instance of each method is held in the Unit.units 'module' variable and then cloned anytime it is requested. So we get many instances of each unit existing. Are you suggesting that we have only one (singleton) instance of, say, a kg unit, which is used in all operations involving a kg? That would be nice, but I think there would be complications where compound units and unit operations come in to play, so it might take a bit of work.
There is a lot of fairly messy code in Unit.rb which provides the versatile functionality for accessing units via names, pluralised names and symbols for single and compound units and units within strings. Unit::escape_multi_word_units is part of this functionality. It basically allow multi word units to be recognised within larger strings. I have never been very happy with most of this parsing and regex code. Although it works fairly well, it just seems way to messy. One implication of removing the ability to configure units at runtime would be that a number of these methods (which basically build lists and regexen) would be static and could therefore be memoized.
Cheers
Andrew
from quantify.
Hi Andrew,
refactoring dimensions.rb was quite a challenge for me because there are so many back and forth references between Unit
, BaseUnit
, Dimensions
etc. With that experience in mind and after having read your comments above I would suggest the following:
1.) I like your idea of always loading a minimal set of default units (convention) and optionally adding more units through configuration. I guess the minimal set should be unity + si_units, right? Then lets make these ones (immutable) singletons.
2.) Make all units immutable. A unit instance should never change its dimensions during its life.
If we multiply two units the result should be a new (immutable) unit and not an updated original unit. That shouldn't be too hard to realize as you already have this nice concept of compound units and you mostly clone the units right now already. Note: Consolidating units (e.g. m^3/m^2) may then result in a reference to the original base unit instance again. I don't see any reason why this could be a problem.
3.) Rethink some of the class concepts: For example, Dimensions.rb
mixes the concept of a single dimension with that of a set of dimensions. Breaking this down into a Dimension.rb
and a Dimensions.rb
would make both comprehension and testing easier for outsiders like me. Another thing could be the extraction of unit name parsing into a parser class on its own. This would concentrate all parsing code into one class and make Unit.rb more lightweight as it then only has to represent 'a unit'.
For my current web project (where quantify_mongoid is used) I suffer heavily from Unit.for() being really, really slow. The scenario is a batch import of thousands of records, each holding several quantities. To ensure that all imported quantities come with valid units, I have a Unit.for() call for each entry. My idea right now is to speed things up using (cached) Unit#unit_label_regex, Unit#unit_symbol_regex etc. If that's not enough I will digg into Unit.rb next to speed it up too.
Cheers,
Carsten
from quantify.
One more thing that comes to my mind: If there's a UnitParser
class this class could also maintain a cache of recently parsed units. Like this, complex unit parsing (think 'm² kg/s³ A') is costly only once.
from quantify.
And another thing:
Why not bootstrap quantify lib through a configurator class, This is responsible for reading (yml) config and to instantiate the system of known units. After having initialized all units it then initializes (resets) the UnitParser
, which triggers (re-)building of the complete set of regexes required to validate and parse units. Like this building regexes (currently one of the most expensive operations - see https://github.com/cblock/quantify/blob/f99b93128ec38ab99c87b25cd432c3fb6b80c1e3/perf/quantity_to_si.profile.pdf) is done only once during (re-) initialization.
from quantify.
Related Issues (20)
- Investigate making units singletons
- Cancelling of units after operations
- Add unit inflections to unit configuration/definition
- Use define_method instead of method missing for loaded units
- Error in boolean clauses in Unit.parse method HOT 1
- Errors not informative in quantity comparison method HOT 1
- Better handling nil values HOT 2
- Add support for i18n HOT 11
- Make unity have blank name and symbol HOT 3
- Fail fast on invalid unit conversion HOT 1
- Make units immutable
- Consider refactoring Dimensions class
- Refactor unit parsing into separate class/module
- Gem::Exception: ruby_code case not handled: Syck::PrivateType HOT 3
- lots of "instance variable @foobar not initialized"
- Infinite loop when trying to convert N/kg to SI
- Missing commas on quantity.rb exception raises
- Error parsing cubic feet HOT 2
- Default type of 'ton' HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from quantify.